【发布时间】:2016-09-23 22:42:57
【问题描述】:
假设我有一个存储客户姓名、设备编号和一些标志的表。一些示例数据如下所示:
[CustomerName], [Device], [A], [B], [C]
'Customer A', '1234', 1, 0, 0
'Customer A', '1235', 1, 1, 1
'Customer A', '1234', 1, 1, 1
'Customer B', '1236', 1, 1, 0
'Customer B', '1236', 1, 0, 0
'Customer C', '1235', 1, 1, 1
我需要一份同时呈现 3 类数据的报告:
- 每个标志的总行数
- 每个客户每个标志的行数
- 每个标志出现在任何行中的唯一设备的数量
使用ROLLUP 创建前两项相对容易,但最后一项比较棘手。我能弄清楚如何做到这一点的唯一方法是使用UNION:
SELECT CASE WHEN (GROUPING([CustomerName]) = 1) THEN 'ALL CUSTOMERS'
ELSE [CustomerName] END [CustomerName],
COUNT(*) [Rows],
SUM(CAST([A] AS [int])) [A],
SUM(CAST([B] AS [int])) [B],
SUM(CAST([C] AS [int])) [C]
FROM [MyTable]
GROUP BY [CustomerName] WITH ROLLUP
UNION
SELECT 'UNIQUE DEVICES',
COUNT(*),
SUM(CASE WHEN [A] > 0 THEN 1 ELSE 0 END),
SUM(CASE WHEN [B] > 0 THEN 1 ELSE 0 END),
SUM(CASE WHEN [C] > 0 THEN 1 ELSE 0 END)
FROM (
SELECT [Device],
COUNT(*) [Rows],
SUM(CAST([A] AS [int])) [A],
SUM(CAST([B] AS [int])) [B],
SUM(CAST([C] AS [int])) [C]
FROM [MyTable]
GROUP BY [Device] ) q
结果:
[CustomerName], [Rows], [A], [B], [C]
'ALL CUSTOMERS', 6, 6, 4, 3
'Customer A', 3, 3, 2, 2
'Customer B', 2, 2, 1, 0
'Customer C', 1, 1, 1, 1
'UNIQUE DEVICES', 3, 3, 3, 2
这对于我现在的目的来说已经足够好了,但是之前没有太多使用 ROLLUP 或 CUBE 的经验,我想我会尝试看看我是否可以摆脱那个 UNION 并拥有一个单SELECT。从examples on MSDN,ROLLUP 支持多个分组,但我不知道如何让它产生我想要的结果。谁能演示如何使用单个 SELECT 来获得这些结果?
【问题讨论】:
-
分组、汇总和多维数据集是分层的,但您想要的输出不是。你所做的是获得你想要的结果的唯一方法:)
-
@P.Salmon 这就是我所害怕的,但我一直在想,如果我像在第二个
SELECT中那样使用双重聚合,那么它是可能的。 -
有一些方法可以让你把它变成一个“单一”查询(即不使用
UNION),但它们都将涉及比你更复杂/更难理解/性能更低的代码已经有了。如果您真的想要一个,或者您可以接受@P.Salmon 基本上是一击毙命,我可以稍后再发布一个示例。
标签: sql sql-server tsql cube rollup