Regroupement SQL

Le regroupement SQL résout le problème des totaux et des sous-totaux dans les scénarios OLAP. Sa syntaxe est divisée en plusieurs catégories, mais le même problème est à résoudre :

ROLLUP et CUBE sont des GROUPING SETS qui encapsulent des règles, et GROUPING SETS sont les règles les plus primitives.

Pour faciliter la compréhension, commençons par un problème et progressons.

tableau du bas

Ce qui précède est l'exemple de tableau du bas, il y a 8 éléments de données, la ville 1, la ville 2 deux villes, en dessous chacune ont la zone 1 ~ 4, chaque élément de données a le nombre de population des données.

Maintenant, je veux calculer la population totale, ainsi que les sous-totaux pour chaque ville. Avant de maîtriser la syntaxe de regroupement, nous ne pouvons l'obtenir qu'après avoir réuni deux instructions select :

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

Mais les deux instructions select sont agrégées deux fois, et les performances ne sont pas une petite surcharge, donc SQL fournit la syntaxe GROUPING SETS pour résoudre ce problème.

JEUX DE GROUPEMENT

GROUP BY GROUPING SETS peut spécifier n'importe quel élément d'agrégation. Par exemple, si nous voulons calculer le total et le total du groupe en même temps, nous devons effectuer un GROUP BY en fonction du contenu vide et effectuer une somme, puis effectuer un GROUP BY selon la ville et effectuer une somme, et la remplacer par GROUPING SETS La description est :

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

GROUPING SETS((), (city, area))indique que le total est calculé ()par et (city, area)agrégé respectivement. Le résultat renvoyé est :

Comme vous pouvez le voir, la ligne avec une valeur NULL est le total que nous voulons, et sa valeur est calculée sans aucune restriction GROUP BY.

De même, nous pouvons également GROUPING SETS((), (city), (city, area), (area))écrire n'importe quel nombre et combinaison de conditions GROUP BY.

Les données calculées par cette règle sont appelées "enregistrement de super groupe". Nous avons constaté que les valeurs NULL générées par les "enregistrements de super regroupement" sont facilement confondues avec les vraies valeurs NULL, donc SQL fournit la fonction GROUPING pour résoudre ce problème.

fonction GROUPEMENT

Le NULL généré par l'enregistrement du supergroupe peut être reconnu comme 1 par la GROUPING()fonction :

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

L'effet spécifique est illustré dans la figure suivante :

可以看到,但凡是超级分组计算出来的字段都会识别为 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。

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

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证

Je suppose que tu aimes

Origine juejin.im/post/7083299385416613919
conseillé
Classement