GROUPING SETS 详解
准确选择您需要的分组
GROUPING SETS 详解 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。
什么是分组集?
编写 GROUP BY 子句时,您定义了一组用于分组的列。但有时您需要在单个查询中执行多种不同的分组——而不必多次运行查询并使用 UNION ALL。
分组集允许您精确指定所需的分组,并在一次数据扫描中全部完成。列表中的每个分组集都会在结果中生成各自的聚合行。
示例表:销售
本课将始终使用 销售表。它记录了按区域、产品类别和金额划分的交易。
运行代码创建并填充该表,以便您跟随每个示例进行操作。
CREATE TABLE sales (
region TEXT,
category TEXT,
amount NUMERIC
);
INSERT INTO sales VALUES
('East', 'Electronics', 500),
('East', 'Clothing', 200),
('West', 'Electronics', 300),
('West', 'Clothing', 400),
('North', 'Electronics', 150),
('North', 'Clothing', 250);旧方法:UNION ALL
在分组集出现之前,要获取多个层级的汇总,就必须编写独立的查询,再使用 UNION ALL 将它们叠加起来。这种方式重复繁琐、可读性较差,而且会多次扫描该表。
下面的示例使用三个独立的 SELECT 语句,返回按区域的总计 AND 按类别的总计。
SELECT region, NULL AS category, SUM(amount) AS total
FROM sales
GROUP BY region
UNION ALL
SELECT NULL, category, SUM(amount)
FROM sales
GROUP BY category
UNION ALL
SELECT NULL, NULL, SUM(amount)
FROM sales;分组集语法
分组集子句位于普通 GROUP BY 内部(或替代普通 GROUP BY)。您可以将每个所需的分组列为一个带括号的列列表。空集 () 表示总计,即完全不进行分组。
这个单一查询完成的工作与上面的三部分 UNION ALL 完全相同,但写法更简洁,并且只扫描一次表。
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region),
(category),
()
);阅读结果
输出中的每一行恰好属于一个分组集。当某列不属于当前分组集时,该列的值就是 NULL。
region = 'East'且category = NULL的行属于(region)集。region = NULL且category = 'Electronics'的行属于(category)集。- 两列均为 NULL 的行是来自
()集的总计。
这些 NULL 是结构性的——它们表示该维度的“所有值”,而不是缺失数据。
多列分组集
每个分组集可以包含多个列。集合 (region, category) 会同时按这两列进行分组,就像普通的 GROUP BY region, category 一样。
将其与单列分组集和总计结合起来,就能通过一个查询生成四层汇总。
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
(category),
()
);分组判定函数
由于 NULL 既可能表示“此列未参与分组”,也可能表示真实的缺失数据,结构化查询语言提供了分组判定函数来区分二者。
GROUPING(col) 在当前分组集中省略了该列时(也就是说,其 NULL 是结构性的)返回 1;当该列参与分组(或具有真实的 NULL 值)时返回 0。
SELECT
region,
category,
SUM(amount) AS total,
GROUPING(region) AS is_region_total,
GROUPING(category) AS is_category_total
FROM sales
GROUP BY GROUPING SETS (
(region),
(category),
()
);替换 NULL 标签
一种常见做法是将结构性的 NULL 替换为描述性标签,从而让报表更易于阅读。使用 CASE WHEN 分组(...) = 1 THEN '全部...' ELSE 列 END,即可仅为汇总行替换标签。
SELECT
CASE WHEN GROUPING(region) = 1 THEN 'All Regions' ELSE region END AS region,
CASE WHEN GROUPING(category) = 1 THEN 'All Categories' ELSE category END AS category,
SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region),
(category),
()
);分组集与 ROLLUP 的比较
ROLLUP(a, b) 是分组集 (a, b), (a), () 的简写形式——它始终沿着层级关系添加小计和总计。
分组集让您拥有完全的控制权:您可以精确选择要显示的组合。如果不需要完整的层级关系,就可以省略相应层级。下面两个查询会生成相同的输出。
-- Using ROLLUP
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY ROLLUP(region, category);
-- Equivalent explicit GROUPING SETS
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
()
);分组集与 CUBE 的比较
CUBE(a, b) 会生成所列各列的所有可能组合:(a, b), (a), (b), ()。它适合进行跨维度分析,但会生成大量行。
分组集允许您只选择关注的组合,使结果更聚焦并让查询运行更快。
-- CUBE produces 4 grouping sets for 2 columns
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY CUBE(region, category);
-- GROUPING SETS: omit the (category)-only set if not needed
SELECT region, category, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
()
);实际应用:销售仪表板
实际的仪表板通常需要在同一个结果集中同时包含行级明细、部门小计和总计。分组集无需应用端聚合或多次往返,就能轻松实现这一点。
此查询会返回每个区域和类别的明细行、仅按区域汇总的小计行,以及单独的总计行,并按排序让总计显示在最后。
SELECT
COALESCE(region, 'TOTAL') AS region,
COALESCE(category, 'ALL') AS category,
SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS (
(region, category),
(region),
()
)
ORDER BY
GROUPING(region),
region NULLS LAST,
GROUPING(category),
category NULLS LAST;快速检查
检验您对分组集的理解。
课程回顾
以下是您对分组集的学习要点:
- 分组集允许您在单个查询中定义多种分组组合,从而替代重复的 UNION ALL 模式。
- 每个集合都作为带括号的列列表,列在
GROUP BY GROUPING SETS (...)中。空集()会生成总计。 - 不在当前集合中的列会在该行中显示为 NULL——使用
GROUPING(col)可以识别这些结构性 NULL。 - ROLLUP 和 CUBE 是常见模式的便捷简写,但分组集可以精确、完整地控制要包含哪些分组。
- 结合 COALESCE 或 CASE WHEN 分组(...),可以在报表中将 NULL 替换为易读的标签。
常见问题解答
「GROUPING SETS 详解」课时是免费的吗?
是的 — 「GROUPING SETS 详解」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。
「GROUPING SETS 详解」这节课中我会学到什么?
准确选择您需要的分组 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「GROUPING SETS 详解」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Academy 课中编写并运行代码吗?
能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 超越单个 GROUP BY
- 使用 ROLLUP 计算小计
- 使用 CUBE 处理所有组合
- GROUPING SETS 详解