真以为自己懂 Group By 了?

共 3127字,需浏览 7分钟

 ·

2021-03-17 09:38

点击蓝色“有关SQL”关注我哟

加个“星标”,天天与10000人一起快乐成长

图 | 榖依米


有读者朋友,翻出 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 

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



--完--





往期精彩:


本号精华合集(三)

外企一道 SQL 面试题,刷掉 494 名候选人

我在面试数据库工程师候选人时,常问的一些题

零基础 SQL 数据库小白,从入门到精通的学习路线与书单








浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报