SQLグループ化は、OLAPシナリオの合計と小計の問題を解決します。その構文はいくつかのカテゴリに分けられますが、同じ問題を解決する必要があります。
ROLLUPとCUBEは、ルールをカプセル化するグループ化セットであり、グループ化セットは最も基本的なルールです。
理解を容易にするために、問題から始めて、上に向かって進んでいきましょう。
下の表
上記はサンプルの下部の表です。8つのデータがあります。都市1、都市2、2つの都市、それぞれの下に領域1〜4があり、各データにはデータの人口番号があります。
次に、各都市の総人口と小計を計算します。グループ化構文を習得する前に、2つのselectステートメントを結合した後でのみそれを取得できます。
SELECT city, sum(people) FROM test GROUP BY city
union
SELECT '合计' as city, sum(people) FROM test
复制代码
ただし、2つのselectステートメントは2回集約され、パフォーマンスは小さなオーバーヘッドではないため、SQLはこの問題を解決するためのGROUPINGSETS構文を提供します。
グループ化セット
GROUP BY GROUPING SETSは、任意の集計項目を指定できます。たとえば、合計とグループ化された合計を同時に計算する場合は、空のコンテンツに従ってGROUP BYの合計を実行してから、それに応じてGROUPBYを実行する必要があります。市に行き、合計を実行します。GROUPINGSETSの説明は次のとおりです。
SELECT
city, area,
sum(people)
FROM test
GROUP BY GROUPING SETS((), (city, area))
复制代码
ここで、GROUPING SETS((), (city, area))
は、合計がそれぞれによって計算()
され、(city, area)
集計されることを示します。返される結果は次のとおりです。
ご覧のとおり、NULL値の行は必要な合計であり、その値はGROUPBYの制限なしで計算されます。
同様に、GROUPBY条件の任意の数と組み合わせをGROUPING SETS((), (city), (city, area), (area))
書き込むます。
このルールで計算されたデータを「スーパーグループレコード」と呼びます。「スーパーグループ化レコード」によって生成されたNULL値は実際のNULL値と簡単に混同されることがわかったため、SQLはこの問題を解決するためのGROUPING関数を提供します。
関数のグループ化
スーパーグループレコードによって生成されたNULLは、次のGROUPING()
関数。
SELECT
GROUPING(city),
GROUPING(area),
sum(people)
FROM test
GROUP BY GROUPING SETS((), (city, area))
复制代码
具体的な効果を次の図に示します。
可以看到,但凡是超级分组计算出来的字段都会识别为 1,我们利用之前学习的 SQL CASE 表达式 将其转换为总计、小计字样,就可以得出一张数据分析表了:
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,以下两种写法是等价的:
SELECT sum(people) FROM test
GROUP BY ROLLUP(city)
-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city))
复制代码
再看一组等价描述:
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)。
类比上面的例子,我们再写两组等价的展开:
SELECT sum(people) FROM test
GROUP BY CUBE(city)
-- 等价于
SELECT sum(people) FROM test
GROUP BY GROUPING SETS((), (city))
复制代码
上面的例子因为只有一项还看不出来,下面两项分组就能看出来了:
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。
如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)