SQL Group By Cube并获得每个组合的总和

时间:2016-05-11 18:38:11

标签: sql-server group-by

我有一个关于在T-SQL中使用Group by Cube选项的问题。我正在使用SQL Server 2012.

所以我有一张如下表:

UserID  | A | B | C | D
------------------------
  1     | 1 | 1 | 1 | 1
  2     | 1 | 1 | 1 | 1
  3     | 0 | 0 | 1 | 1
  4     | 1 | 1 | 0 | 0
  5     | 1 | 1 | 1 | 1
  6     | 1 | 1 | 0 | 0
  7     | 1 | 1 | 1 | 0
  8     | 1 | 1 | 0 | 0
  9     | 1 | 1 | 0 | 0
  10    | 1 | 1 | 0 | 0
  11    | 1 | 1 | 1 | 1
  12    | 0 | 1 | 1 | 1
  13    | 1 | 1 | 1 | 0
  14    | 1 | 1 | 0 | 0
  15    | 1 | 1 | 1 | 0
  16    | 1 | 1 | 1 | 0
  17    | 1 | 1 | 1 | 1
  18    | 1 | 1 | 1 | 1
  19    | 1 | 1 | 1 | 0
  20    | 1 | 1 | 0 | 0
  21    | 1 | 1 | 1 | 1
  22    | 0 | 1 | 1 | 1

在A,B,C和D上使用Group By Cube,我得到15个组合,不包括空集。现在,我想找到每个组合下有多少用户。如果没有用户有这样的组合,我仍然希望看到组合,但具有用户数的列可以为零。所以结果输出应该是

A   B   C   D   Qty
1               0
    1           0
        1       0
            1   0
1   1           7
1       1       0
1           1   0
1   1   1       5
1   1   1   1   7
    1   1       0
    1       1   0
    1   1   1   2
        1   1   1
1   1       1   0
1       1   1   0

我能以任何方式实现这一目标吗?任何帮助将非常感谢!

2 个答案:

答案 0 :(得分:2)

我的方法是创建一个包含所有可能性的表格,并对正常LEFT JOIN使用GROUP BY

如果这是偶尔运行,也许临时表可能没问题。如果没有,永久表将是最好的,因此您不会不断创建和删除临时表。

/* Create a temporary table */
CREATE TABLE TEMPSO11052016 (A int, B int, C int, D int);

/* Insert all possibilities on the temporary table */
INSERT INTO TEMPSO11052016 (A, B, C, D)
VALUES (1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(0,1,1,1),
       (1,1,0,0),(1,0,1,0),(0,1,1,0),(1,0,0,1),(0,1,0,1),(0,0,1,1),
       (1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1),(0,0,0,0);

/* Run the selection query */
SELECT T.A, T.B, T.C, T.D, ISNULL(CT, 0)         
FROM TEMPSO11052016 T
LEFT JOIN (SELECT A, B, C, D, COUNT(ID) AS CT FROM SO11052016 GROUP BY A, B, C, D) S
ON S.A=T.A AND S.B=T.B AND S.C=T.C AND S.D=T.D;

/* Drop the temporary table */
DROP TABLE TEMPSO11052016;

答案 1 :(得分:1)

与@ Edu的回复类似,但使用交叉联接创建“所有组合”表。

; with CTE as (select '' as Value
               union all
               select '1')
, CTE2 as (Select a.Value as A, b.Value as B, c.Value as C, d.Value as D  
                    from CTE a
                    cross join CTE b
                    cross join CTE c
                    cross join CTE d)

select a.*, count(distinct b.UserID) from CTE2 a
left join #mydata b
on a.a = b.a and a.b = b.b and a.c = b.c and a.d = b.d
group by a.A, a.B, a.C, a.D
order by a.A, a.B, a.C, a.D