0Pricing
SQL Interview Prep · 课时

按多列和表达式分组

掌握组合分组键,以及如何按计算值分组

按多列和表达式分组 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。

超越单个分组键

实际报表很少只按一列分组。面试官会将问题从'按地区统计销售额'升级为'按地区、按月份统计销售额',以了解您是否理解复合分组键。

规则可以直接扩展:在 GROUP BY 中列出更多列,就会为这些列的每个不同组合创建一行。

多列意味着什么

当您写出 GROUP BY region, product 时,分组键就是(地区,产品)这一对值。每个不同的组合都会成为一行输出。

  • 5 个地区和 4 种产品最多会产生 20 个分组。
  • 从未出现过的组合不会生成任何行。
  • GROUP BY 中列的顺序不会改变结果集,只是有时会影响执行计划。
SELECT region, product, SUM(amount) AS total
FROM sales
GROUP BY region, product;

仍须遵守 SELECT 规则

核心约束并没有放宽。SELECT 中每个非聚合列都必须出现在 GROUP BY 中。对于复合键,只需将这些列全部列出即可。

在多键分组中漏掉一列,是面试压力下最常见的疏漏。请确保 GROUP BY 列表与 SELECT 中的非聚合列完全对应。

-- Both region and product appear in GROUP BY
SELECT region, product,
       COUNT(*) AS orders,
       AVG(amount) AS avg_amount
FROM sales
GROUP BY region, product;

按表达式分组

您可以按计算值分组,而不仅仅是按原始列分组。一个常见要求是按月份统计销售额,这意味着要按截断后的日期或提取出的日期部分分组。

GROUP BY 中的表达式必须与 SELECT 中的表达式一致。数据库引擎会按照计算结果进行分组。

SELECT DATE_TRUNC('month', order_date) AS month,
       SUM(amount) AS monthly_total
FROM sales
GROUP BY DATE_TRUNC('month', order_date);

使用 CASE 分桶

一种强大的模式是按 CASE 表达式分组,从而创建自定义分桶。这样无需查找表,就能生成'小额 / 中额 / 大额订单'汇总。

面试官喜欢这个问题,因为它会同时测试 CASE 逻辑和按派生值分组的能力。

SELECT CASE
         WHEN amount < 50  THEN 'small'
         WHEN amount < 200 THEN 'medium'
         ELSE 'large'
       END AS bucket,
       COUNT(*) AS orders
FROM sales
GROUP BY CASE
         WHEN amount < 50  THEN 'small'
         WHEN amount < 200 THEN 'medium'
         ELSE 'large'
       END;

按列位置分组

许多数据库方言允许按序号位置分组:GROUP BY 1, 2 表示按 SELECT 中的第一列和第二列分组。这种写法简洁,但很脆弱。

面试官可能会接受这种写法,但请注意其中的风险:重新排列 SELECT 列表会悄悄改变分组方式。在生产代码中,请优先使用明确的表达式。

-- 1 = month expression, 2 = region
SELECT DATE_TRUNC('month', order_date) AS month,
       region, SUM(amount)
FROM sales
GROUP BY 1, 2;

NULL 会形成独立分组

分组中的一个 NULL 处理陷阱是:当分组列包含 NULL 时,所有 NULL 行都会合并为一个分组。

这与相等比较不同,在相等比较中 NULL 永远不等于 NULL。但在分组时,NULL 会被视为'相同',并形成一个分桶。面试官很喜欢这个看似矛盾的现象。

-- Rows with region IS NULL all land in one group
SELECT region, COUNT(*) AS orders
FROM sales
GROUP BY region;

使用 GROUPING SETS 生成多个层级

如果要在一个查询中生成多个分组粒度,请使用 GROUPING SETS。它会计算列出的每组键,并将结果合并起来。

这体现了中高级水平:无需编写三个独立查询再使用 UNION,一个语句就能同时返回按地区、按产品的汇总以及总计。

SELECT region, product, SUM(amount) AS total
FROM sales
GROUP BY GROUPING SETS ((region), (product), ());

ROLLUP 和 CUBE

ROLLUP 和 CUBE 是常见分组集合的简写。ROLLUP(region, product) 会生成地区加产品的明细、地区小计以及总计,非常适合层级报表。

CUBE 会生成所列各列的所有组合。了解这些功能,可以体现候选人确实编写过实际的报表查询。

SELECT region, product, SUM(amount) AS total
FROM sales
GROUP BY ROLLUP (region, product);

示例:按月统计地区报表

综合运用这些概念:统计每个地区每个月的销售总额和平均销售额,只保留已完成的订单,并按便于阅读的方式排序。

WHERE 先缩小行的范围,复合键按地区和月份表达式分组,ORDER BY 则排列输出结果。这是数据分析师面试中典型的完整回答。

SELECT region,
       DATE_TRUNC('month', order_date) AS month,
       SUM(amount) AS total,
       AVG(amount) AS avg_order
FROM sales
WHERE status = 'completed'
GROUP BY region, DATE_TRUNC('month', order_date)
ORDER BY region, month;

如何清晰地说出推理过程

遇到任何复合分组问题时,请明确说出分组键:'我按 X 和 Y 的组合进行分组,因此每个不同的(X,Y)组合都会得到一行。'

然后确认每个非聚合的 SELECT 列都包含在该键中,并说明 NULL 会合并为一个分组。这种有条理的讲解方式正是中级面试所看重的。

快速检查

请思考复合分组键的工作方式。

回顾

复合键:列出多列会为每个不同组合生成一行;每个非聚合的 SELECT 列都必须包含在该键中。

  • 您可以按表达式、CASE 分桶或序号位置分组(按位置分组很脆弱)。
  • 分组列中的 NULL 会合并为一个分组。
  • GROUPING SETS、ROLLUP 和 CUBE 可以在一个查询中生成多个分组层级。
  • 请在分组前将行筛选条件放入 WHERE。

常见问题解答

「按多列和表达式分组」课时是免费的吗?

是的 — 「按多列和表达式分组」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。

「按多列和表达式分组」这节课中我会学到什么?

掌握组合分组键,以及如何按计算值分组 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Interview Prep 需要有经验吗?

无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「按多列和表达式分组」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 SQL Interview Prep 课中编写并运行代码吗?

能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. SELECT 列的 GROUP BY 规则
  2. HAVING 与 WHERE
  3. 按多列和表达式分组
  4. 统计并筛选分组
← 返回 SQL Interview Prep