当前位置: 首页 > Web前端 > HTML

SQL分组

时间:2023-03-28 14:55:38 HTML

SQL分组解决了OLAP场景下的合计和小计问题。它的语法分为几类,但解决的是同一个问题:ROLLUP和CUBE是封装规则的GROUPINGSETS,而GROUPINGSETS是最原始的规则。为了便于理解,让我们从一个问题开始,逐层递进。上面的底表是示例底表,一共有8条数据,city1和city2是两个城市,每条数据下面都有region1到4,每条数据都有该地区的人口数据。现在我想计算每个城市的总人口和小计人口。在掌握分组语法之前,我们只能通过两个select语句的并集得到:SELECTcity,sum(people)FROMtestGROUPBYcityunionSELECT'total'ascity,sum(people)FROMtest但两个select语句是聚合的两次,性能是个不小的开销,所以SQL提供了GROUPINGSETS语法来解决这个问题。GROUPINGSETSGROUPBYGROUPINGSETS可以指定任意聚合项。比如我们要同时计算合计和分组合计,需要根据空内容进行GROUPBY进行求和,然后根据城市进行GROUPBY再进行求和,替换与分组集。描述是:SELECTcity,area,sum(people)FROMtestGROUPBYGROUPINGSETS((),(city,area))其中GROUPINGSETS((),(city,area))表示根据(),(city)聚合,面积)分别计算总和。返回结果为:可以看到,值为NULL的那一行就是我们想要的合计,它的值是在没有任何GROUPBY限制的情况下计算出来的。同样的,我们也可以写出GROUPINGSETS((),(city),(city,area),(area))等任意数量和组合的GROUPBY条件。按此规则计算出的数据称为“超级组记录”。我们发现“超级组记录”产生的NULL值很容易和真正的NULL值混淆,所以SQL提供了GROUPING函数来解决这个问题。GROUPING函数对超分组记录产生的NULL可以被GROUPING()函数识别为1:SELECTGROUPING(city),GROUPING(area),sum(people)FROMtestGROUPBYGROUPINGSETS((),(city,area))具体效果如下图所示:可以看到,超分组计算出来的所有字段都会被识别为1,我们用之前学过的SQLCASE表达式,转换成总计和小计的词,我们可以得到一个数据分析表:SELECTCASEWHENGROUPING(city)=1THEN'total'ELSEcityEND,CASEWHENGROUPING(area)=1THEN'subtotal'ELSEareaEND,sum(people)FROMtestGROUPBYGROUPINGSETS((),(city,area))然后前台表格显示时,第一行“合计”和“小计”单元格合并为“合计”,合计的BI可视化分析功能完成了。ROLLUPROLLUP意为向上卷起,是一个具有特定规则的GROUPINGSETS。下面两种写法是等价的:SELECTsum(people)FROMtestGROUPBYROLLUP(city)--等价于SELECTsum(people)FROMtestGROUPBYGROUPINGSETS((),(city))看一组等价的描述:SELECTsum(people)FROMtestGROUPBYROLLUP(city,area)——相当于SELECTsum(people)FROMtestGROUPBYGROUPINGSETS((),(city),(city,area))你找到规律了吗?ROLLUP将按顺序“卷起”GROUPBY的内容。使用GROUPING函数确定超组记录同样适用于ROLLUP。CUBECUBE则不同,它扩展了内容的所有可能性(因此得名CUBE)。类比上面的例子,我们写两组等价展开式:SELECTsum(people)FROMtestGROUPBYCUBE(city)--等价于SELECTsum(people)FROMtestGROUPBYGROUPINGSETS((),(city))中上面的例子,因为只有一项不可见,所以可以看到以下两组:,(city),(area),(city,area))所谓CUBE,就是对多维形状的描述。二维有2^1次展开,三维有2^2次展开,四次元有2^2次展开,五个维度等等。可以想象,如果用CUBE来描述很多组合,复杂度会爆炸。综上所述,学习了GROUPING语法后,作为前端同学的你就不会再被这个问题困扰了:产品已经启用了合计和小计,是应该多取一个数还是放在一起?这个问题的标准答案和原理在这篇文章里。PS:对于不支持GROUPING语法的数据库,想办法屏蔽是降级方案,就像前端polyfill一样。至于如何屏蔽,参考文章开头提到的两个SELECT+UNION。讨论地址为:Jingdu《SQL grouping》·Issue#406·ascoders/weekly想参与讨论的请点这里,每周都有新话题,周末或周一发布。前端精读——帮你过滤靠谱的内容。关注前端精读微信公众号版权声明:免费转载-非商业-非衍生保留属性(CreativeCommons3.0License)