SQL 查询 - 如何选择显示组、组总计、总计?

use*_*867 2 sql-server aggregate group-by

我看过一些建议,但想知道在不使用子查询或不必要的联接的情况下从数据表中选择组、组总数、总计的最佳方法。

我最初的想法是这样的:

select   product_family, 
         sum(widgets), 
         sum(widgets) over ()
from     table.widget
group by product_family
Run Code Online (Sandbox Code Playgroud)

或以下内容:

select   product_family, 
         sum(widgets), 
         sum(widgets) over (partition by all_field)
from     table.widget
group by product_family
Run Code Online (Sandbox Code Playgroud)

显然这两种方法都不起作用。我知道一个分区的顺序可能比实际的行/组更高,但除了第一个示例将其留空之外,我不知道如何按“所有”进行分区。但是,它打破了 group by 语句。

我能找到的最好的是这样的:

select product_family, 
       family_sum, 
       sum(family_sum) over () as grand_sum 
from (
      select   product_family, sum(widgets)
      from     table.widget
      group by product_family
     ) as A
Run Code Online (Sandbox Code Playgroud)

不过,这仍然涉及子查询,这没关系。我只是觉得我在这里缺少一个简单的功能。

Han*_*non 5

GROUP BY ROLLUP 做你想做的。

举个例子:

SELECT o.schema_id
    , type_desc
    , [Count Of Objects] = COUNT(o.object_id)
FROM sys.objects o
GROUP BY ROLLUP (o.schema_id, o.type_desc)
Run Code Online (Sandbox Code Playgroud)

这会产生以下输出:

?????????????????????????????????????????????????????? ???????
? 架构_id ? 类型描述?对象数量?
?????????????????????????????????????????????????????? ???????
? 1 ? PRIMARY_KEY_CONSTRAINT ?7 ?
? 1 ? 服务队列?3 ?
? 1 ? 用户表?8 ?
? 1 ? 空值 ?18 ?
? 4 ? 内部_表?16 ?
? 4 ? 系统表?72 ?
? 4 ? 空值 ?88 ?
? 空值 ?空值 ?106 ?
?????????????????????????????????????????????????????? ???????

所述NULL在前两列表示示出卷起的量。

为了使它“漂亮”,您可以对NULL汇总值使用一些替换:

SELECT [Schema Name] = CASE 
        WHEN s.name IS NULL THEN 
            '[Grand Total]' 
        ELSE s.name 
        END
    , [Object Type] = CASE 
        WHEN o.type_desc IS NULL THEN 
            '[Total - ' + COALESCE(s.name, 'Overall') + ']' COLLATE SQL_Latin1_General_CP1_CI_AS 
        ELSE o.type_desc 
        END
    , [Count of Objects] = COUNT(o.object_id)
FROM sys.objects o
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
GROUP BY ROLLUP (s.name, o.type_desc);
Run Code Online (Sandbox Code Playgroud)
?????????????????????????????????????????????????????? ????????????
? 架构名称 ? 对象类型 ? 对象数 ?
?????????????????????????????????????????????????????? ????????????
? 德博?PRIMARY_KEY_CONSTRAINT ?7 ?
? 德博?服务队列?3 ?
? 德博?用户表?8 ?
? 德博?[总计 - dbo] ? 18 ?
? 系统?内部_表?16 ?
? 系统?系统表?72 ?
? 系统?[总-系统] ? 88 ?
? [累计] ?[总 - 总] ? 106 ?
?????????????????????????????????????????????????????? ????????????

  • `GROUP BY GROUPING SETS()` 是现代方式(我不记得 `ROLLUP` 是否已被弃用)。 (2认同)
  • 不推荐使用的语法是 `GROUP BY ... WITH ROLLUP` 和 `GROUP BY ... WITH CUBE`,它们是 SQL Server 特定的。`ROLLUP()` 和 `CUBE()` GROUP BY 函数是在 SQL Server 2008 中引入的,[它们是 SQL 标准的一部分](https://www.red-gate.com/simple-talk/sql/ t-sql-programming/questions-about-cube-rollup-and-grouping-sets-that-you-were-too-shy-to-ask/#Toc434316594)。 (2认同)

ype*_*eᵀᴹ 5

GROUP BY ROLLUP或者 - 更好 -GROUP BY GROUPING SETS如果您想要额外的行来显示总计,则最好。

如果您想要每一行(另一列)中的总计,那么您的查询需要进行细微调整。SUM(widgets)您可以在窗口函数中使用聚合:

select   product_family, 
         sum(widgets)              as total, 
         sum(sum(widgets)) over () as grand_total
from     table.widget
group by product_family ;
Run Code Online (Sandbox Code Playgroud)