Search code examples
sqlsql-servert-sqlcubeolap-cube

T-SQL :: use GROUP BY CUBE to generate all possible combinations


In a post I found that I can use GROUP BY CUBE to find all possible combinations:

select concat(a,b,c,d)
from (select 'a','b','c','d') as t(a,b,c,d)
group by cube(a,b,c,d)
having len(concat(a,b,c,d)) = 3

The code is pretty because is very easy to understand. I would like to use the same code but with int instead of char. Basically I would like to find all possible combinations of numbers (1,2,3,4).

The goal is to sum them and generate all possible totals:

  • 1 + 2 + 3 = 6
  • 2 + 3 + 4 = 7
  • 3 + 4 + 1 = 8
  • etc..

I'm trying to resolve a knapsack problem in T-SQL and I would like to see if GROUP BY CUBE can be a solution


Solution

  • You need to take NULLs into account more explicitly, but something like this:

    select coalesce(a, 0) + coalesce(b, 0) + coalesce(c, 0) + coalesce(d, 0)
    from (values (1, 2, 3, 4)) t(a,b,c,d)
    group by cube(a,b,c,d)
    having (case when a is not null then 1 else 0 end +
            case when b is not null then 1 else 0 end +
            case when c is not null then 1 else 0 end +
            case when d is not null then 1 else 0 end
           ) = 3;
    

    Here is a db<>fiddle.

    I should note that an alternative method of doing this uses explicit joins:

    with t as (
          select t.*
          from (values (1), (2), (3), (4)) t(x)
         )
    select t1.x + t2.x + t3.x
    from t t1 join
         t t2
         on t1.x < t2.x join
         t t3
         on t2.x < t3.x;
    

    These are not exactly the same if the values can be repeated. However, you might find that the join version is faster on larger amounts of data.