真以为自己懂 Group By 了?

楼主
讨论所有与SQL有关的内容

有读者朋友,翻出 2018 年的文章,吐槽了下排版。

是的,这种排版就连现在的我,都看不下去了。于是,我重新格式化下,发出来,弥补下对各位看官的照顾不周。

这篇文章主要细讲 Group by,各位能一眼看懂这条语句在做什么吗?

SELECT OrderMonth,City,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly 
GROUP BY 
 Cube(OrderMonth,City) 
ORDER BY OrderMonth DESC,City

前两天我认认真真在看 MSDN 的文档,我发现我们的开发,写的明细列表和求和运算, 是动态 SQL 拼起来的:

  • 先查询了明细列表,放在一段动态 SQL 里面
  • 然后在这段动态 SQL 的外层,包了一层做了求和计算

这时,我们上次文章提到过的资深开发(当然2021年现在人家已是互联网头部开发副总),过来了,看到我在看 Group By,觉得很奇怪:“ Group By 有什么好看的 ”。我就把上面那条 SQL 给他看了,他看了连连摇头。

我说," 我觉得我们程序里的动态 SQL, 这么写不是很优雅,于是想借助官方文档,看看是不是另有技巧。果不其然, Group by 的写法还是可以很炫!"

记录如下:


/*---------------------------




Gruop By 子句:


1.Plain Group By 
2.RollUp 
3.Cube
4.Grouping Set


*----------------------------*/


CREATE TABLE dbo.FctSalesMonthly (
 ID BIGINT IDENTITY(1, 1) NOT NULL
 ,OrderMonth INT NULL
 ,City VARCHAR(20)
 ,OrderAmount INT
 );


INSERT INTO dbo.FctSalesMonthly (
 OrderMonth
 ,City
 ,OrderAmount
 )
SELECT *
FROM (
 VALUES (
  201701
  ,'Shanghai'
  ,100
  )
  ,(
  201701
  ,'HangZhou'
  ,200
  )
  ,(
  201701
  ,'Suzhou'
  ,300
  )
  ,(
  201702
  ,'Shanghai'
  ,500
  )
  ,(
  201702
  ,'Chongqing'
  ,600
  )
  ,(
  201702
  ,'Suzhou'
  ,800
  )
 ) tmp(OrderMonth, City, OrderAmount)

第一个怪写法:Cube

SELECT OrderMonth
 ,City
 ,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly
GROUP BY Cube(OrderMonth, City)
ORDER BY OrderMonth DESC,City

第二个怪写法:RollUp

SELECT OrderMonth
 ,City
 ,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly
GROUP BY RollUp(OrderMonth, City)
ORDER BY OrderMonth DESC,City

Cube 与 RollUp 的区别:

  • 当只有一个维度作总计的时候,Cube 与 RollUp 实现的结果是一样的,都是分计加总计;

  • 当有2个或以上的维度作总计的时候,总计方法发生了变化:

  1. Rollup 的有向性 : 按照 literal 顺序, 从右到左的向上汇总,直到聚合了所有的维度数据;
  2. Cube 的自由组合性:将参与的每个维度,都按照 Rollup 的汇总方式,从左到右,从右到左,分别上卷汇总

第三个怪写法:Grouping Set

Grouping Set

  • 将参与的每个维度作分类统计,但不包含总计,使用()表达式将总计包含进来;
  • 将Cube,RollUp 组合在一个表达式里面

按照每个维度做分计,但是不计算总计:

SELECT OrderMonth,City,OrderDay,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly 
GROUP BY 
 Grouping Sets  (OrderMonth,City,OrderDay)
ORDER BY OrderMonth 

按照每个维度做分计,并计算总计:

SELECT OrderMonth,City,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly 
GROUP BY 
 Grouping Sets  (OrderMonth,City,())
ORDER BY OrderMonth 

怎么样,是不是很有意思呢?

分享扩散:

沙发
发表于 2021-11-16 16:07:04

不错,我也在用,但不是所有数据库都支持

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

返回顶部 返回列表