前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQL grouping

SQL grouping

作者头像
黄子毅
发布2022-04-18 14:43:31
7280
发布2022-04-18 14:43:31
举报
文章被收录于专栏:前端精读评论

SQL grouping 解决 OLAP 场景总计与小计问题,其语法分为几类,但要解决的是同一个问题:

ROLLUP 与 CUBE 是封装了规则的 GROUPING SETS,而 GROUPING SETS 则是最原始的规则。

为了方便理解,让我们从一个问题入手,层层递进吧。

底表

以上是示例底表,共有 8 条数据,城市1、城市2 两个城市,下面各有地区1~4,每条数据都有该数据的人口数。

现在想计算人口总计,以及各城市人口小计。在没有掌握 grouping 语法前,我们只能通过两个 select 语句 union 后得到:

代码语言:javascript
复制
SELECT city, sum(people) FROM test GROUP BY city
union
SELECT '合计' as city, sum(people) FROM test

但两条 select 语句聚合了两次,性能是一个不小的开销,因此 SQL 提供了 GROUPING SETS 语法解决这个问题。

GROUPING SETS

GROUP BY GROUPING SETS 可以指定任意聚合项,比如我们要同时计算总计与分组合计,就要按照空内容进行 GROUP BY 进行一次 sum,再按照 city 进行 GROUP BY 再进行一次 sum,换成 GROUPING SETS 描述就是:

代码语言:javascript
复制
SELECT 
city, area,
sum(people)
FROM test
GROUP BY GROUPING SETS((), (city, area))

其中 GROUPING SETS((), (city, area)) 表示分别按照 ()(city, area) 聚合计算总计。返回结果是:

可以看到,值为 NULL 的行就是我们要的总计,其值是没有任何 GROUP BY 限制算出来的。

类似的,我们还可以写 GROUPING SETS((), (city), (city, area), (area)) 等任意数量、任意组合的 GROUP BY 条件。

通过这种规则计算的数据我们称为 “超级分组记录”。我们发现 “超级分组记录” 产生的 NULL 值很容易和真正的 NULL 值弄混,所以 SQL 提供了 GROUPING 函数解决这个问题。

函数 GROUPING

对于超级分组记录产生的 NULL,是可以被 GROUPING() 函数识别为 1 的:

代码语言:javascript
复制
SELECT 
GROUPING(city),
GROUPING(area),
sum(people)
FROM test
GROUP BY GROUPING SETS((), (city, area))

具体效果见下图:

可以看到,但凡是超级分组计算出来的字段都会识别为 1,我们利用之前学习的 SQL CASE 表达式 将其转换为总计、小计字样,就可以得出一张数据分析表了:

代码语言:javascript
复制
SELECT 
CASE WHEN GROUPING(city) = 1 THEN '总计' ELSE city END,
CASE WHEN GROUPING(area) = 1 THEN '小计' ELSE area END,
sum(people)
FROM test
GROUP BY GROUPING SETS((), (city, area))

然后前端表格展示时,将第一行 “总计”、“小计” 单元格合并为 “总计”,就完成了总计这个 BI 可视化分析功能。

ROLLUP

ROLLUP 是卷起的意思,是一种特定规则的 GROUPING SETS,以下两种写法是等价的:

代码语言:javascript
复制
SELECT sum(people) FROM test
GROUP BY ROLLUP(city)

-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city))

再看一组等价描述:

代码语言:javascript
复制
SELECT sum(people) FROM test
GROUP BY ROLLUP(city, area)

-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city), (city, area))

发现规律了吗?ROLLUP 会按顺序把 GROUP BY 内容 “一个个卷起来”。用 GROUPING 函数判断超级分组记录对 ROLLUP 同样适用。

CUBE

CUBE 又有所不同,它对内容进行了所有可能性展开(所以叫 CUBE)。

类比上面的例子,我们再写两组等价的展开:

代码语言:javascript
复制
SELECT sum(people) FROM test
GROUP BY CUBE(city)

-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city))

上面的例子因为只有一项还看不出来,下面两项分组就能看出来了:

代码语言:javascript
复制
SELECT sum(people) FROM test
GROUP BY CUBE(city, area)

-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city), (area), (city, area))

所谓 CUBE,是一种多维形状的描述,二维时有 2^1 种展开,三维时有 2^2 种展开,四维、五维依此类推。可以想象,如果用 CUBE 描述了很多组合,复杂度会爆炸。

总结

学习了 GROUPING 语法,以后前端同学的你不会再纠结这个问题了吧:

产品开启了总计、小计,我们是额外取一次数还是放到一起获取啊?

这个问题的标准答案和原理都在这篇文章里了。PS:对于不支持 GROUPING 语法数据库,要想办法屏蔽,就像前端 polyfill 一样,是一种降级方案。至于如何屏蔽,参考文章开头提到的两个 SELECT + UNION。

讨论地址是:精读《SQL grouping》· Issue #406 · ascoders/weekly

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端精读评论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 底表
  • GROUPING SETS
  • 函数 GROUPING
  • ROLLUP
  • CUBE
  • 总结
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档