我有这个代码,它总结了某个项目的数量 ( itemid) 及其产品日期代码 ( proddte)。
select sum(qty), itemid, proddte
from testtable where ....
group by itemid, proddte
Run Code Online (Sandbox Code Playgroud)
我想要做的是让所有总的qty不管itemid/proddte。我试过了:
select sum(qty), itemid, proddte, sum(qty) over() as grandtotal
from testtable
where ....
group by itemid, proddte
Run Code Online (Sandbox Code Playgroud)
但它说我也应该qty在group by条款中。如果我这样做,结果将不等于我的预期结果。
它并不绝对需要表示为一个单独的列,每一行都具有相同的值。只要我可以显示总体总数,任何表示都可以接受。
ype*_*eᵀᴹ 10
这也是有效的语法:
sum(sum(qty)) over ()
Run Code Online (Sandbox Code Playgroud)
当人们第一次看到它时会有点混乱,但您只需要记住窗口函数 - 例如sum() over ()- 在之后应用,group by因此可以出现在按查询组的选择列表中的所有内容都可以放置在窗口聚合中。所以(qty不能但是)sum(qty)可以放在里面sum() over ():
select sum(qty), itemid, proddte,
sum(sum(qty)) over () as grandtotal
from testtable
where ....
group by itemid, proddte ;
Run Code Online (Sandbox Code Playgroud)
话虽如此,我更喜欢GROUPING SETSAaron Bertrand 提供的查询。总和需要显示一次,而不是每一行。
另请注意,虽然总和可用于计算总和,但如果您想要总计数,则必须使用计数总和(而不是计数!):
sum(count(*)) over () as grand_count
Run Code Online (Sandbox Code Playgroud)
如果想要整个表的平均值,那就更复杂了:
sum(sum(qty)) over ()
/ sum(count(qty)) over () as grand_average
Run Code Online (Sandbox Code Playgroud)
因为平均值的平均值与整体的平均值不同。(如果您尝试使用,avg(avg(qty)) over ()您会发现它产生的结果可能与上述总体平均值不同。)
CREATE TABLE #foo
(
itemid int,
proddte date,
qty int
);
INSERT #foo(itemid,proddte,qty) VALUES
(1,'20140101',5),(1,'20140102',7),(2,'20150101',10);
-- if it really needs to be a column with the same value
-- in every row, just calculate once and assign it to a variable
DECLARE @sum int = (SELECT SUM(qty) FROM #foo);
SELECT itemid, proddte, GroupedSum = SUM(qty), GrandTotal = @sum
FROM #foo
GROUP BY itemid, proddte;
-- if the grand total can be expressed on its own row,
-- you can use GROUP BY GROUPING SETS:
SELECT itemid, proddte, SUM(qty)
FROM #foo GROUP BY GROUPING SETS((),(itemid,proddte));
-- if that syntax is confusing, you can use a less
-- efficient UNION ALL:
SELECT itemid, proddte, SUM(qty)
FROM #foo GROUP BY itemid,proddte
UNION ALL
SELECT NULL, NULL, SUM(qty)
FROM #foo;
GO
DROP TABLE #foo;
Run Code Online (Sandbox Code Playgroud)
该GROUP BY GROUPING SETSIS基本上是一个UNION ALL。该()装置只取SUM不管分组,列出的任何其他基团被单独聚合。试着GROUP BY GROUPING SETS ((itemid),(itemid,proddte))看看有什么不同。
有关更多详细信息,请参阅文档:
将 GROUP BY 与 ROLLUP、CUBE 和 GROUPING SETS 结合使用
正如 Andriy 提到的,上面的查询也可以使用:
GROUP BY ROLLUP( (itemid,proddte) )
Run Code Online (Sandbox Code Playgroud)
请注意,那里的两列包含在一对额外的括号中,使它们成为一个单元。Andriy编写了一个托管在 Stack Exchange Data Explorer 上的演示。
| 归档时间: |
|
| 查看次数: |
15145 次 |
| 最近记录: |