主题
面试速答(先看这里)
**一句话结论:**这里,可以使用 CASE WHEN THEN 用来根据条件为每个 product 创建一列,并通过 SUM 聚合同一年份的销售数据,达到行转列的效果。
60秒标准回答:
所谓行转列,就是假设有如下数据表 sales
要将 product 列的不同值(A 和 B)变为列标题, year 作为行标题,生成如下结果
这里,可以使用 CASE WHEN THEN 用来根据条件为每个 product 创建一列,并通过 SUM 聚合同一年份的销售数据,达到行转列的效果
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**所谓行转列,就是假设有如下数据表 sales :
- **要点2:**要将 product 列的不同值(A 和 B)变为列标题, year 作为行标题,生成如下结果:
- **要点3:**还可以使用 IF 实现类似 CASE WHEN 的功能:
- **要点4:**所谓列转行,假设有如下数据表 sales_data :
- **要点5:**通常是使用UNION ALL 实现:
**记忆锚点:**product → sales → CASE → WHEN → year → SUM
加分表达:
- SUM(CASE WHEN product = 'A' THEN sales ELSE 0 END) AS A : 使用 CASE WHEN 判断 product 是否为 A : 如果是 A ,则返回该行的 sales 值。
- 如果不是 A ,则返回 0 。
追问准备:
- 围绕「product」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「sales」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「CASE」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
行转列
所谓行转列,就是假设有如下数据表 sales:
| id | year | product | sales |
|---|---|---|---|
| 1 | 2020 | A | 100 |
| 2 | 2020 | B | 200 |
| 3 | 2021 | A | 150 |
| 4 | 2021 | B | 300 |
要将 product 列的不同值(A 和 B)变为列标题,year 作为行标题,生成如下结果:
| year | A | B |
|---|---|---|
| 2020 | 100 | 200 |
| 2021 | 150 | 300 |
这里,可以使用CASE WHEN THEN 用来根据条件为每个 product 创建一列,并通过 SUM 聚合同一年份的销售数据,达到行转列的效果。
java
SELECT
year,
SUM(CASE WHEN product = 'A' THEN sales ELSE 0 END) AS A,
SUM(CASE WHEN product = 'B' THEN sales ELSE 0 END) AS B
FROM sales
GROUP BY year;简答解释下:
**SUM(CASE WHEN product = 'A' THEN sales ELSE 0 END) AS A**:使用
CASE WHEN判断product是否为A:如果是
A,则返回该行的sales值。如果不是
A,则返回0。然后,
SUM函数将每个year内所有product = 'A'的sales值加总,最终得到该year对应的A产品总销售额。
还可以使用IF实现类似CASE WHEN的功能:
java
SELECT
year,
SUM(IF(product = 'A', sales, 0)) AS A,
SUM(IF(product = 'B', sales, 0)) AS B
FROM sales
GROUP BY year;列转行
所谓列转行,假设有如下数据表 sales_data :
| year | A | B |
|---|---|---|
| 2020 | 100 | 200 |
| 2021 | 150 | 300 |
转成如下格式结构:
| year | product | sales |
|---|---|---|
| 2020 | A | 100 |
| 2020 | B | 200 |
| 2021 | A | 150 |
| 2021 | B | 300 |
通常是使用UNION ALL 实现:
sql
SELECT
year,
'A' AS product,
A AS sales
FROM sales_data
UNION ALL
SELECT
year,
'B' AS product,
B AS sales
FROM sales_data;
ORDER BY year, product;- 第一个
SELECT子查询提取了A列的数据,并将A作为product值: - 输出行:
(2020, 'A', 100)和(2021, 'A', 150)。 - 第二个
SELECT子查询提取了B列的数据,并将B作为product值: - 输出行:
(2020, 'B', 200)和(2021, 'B', 300)。 UNION ALL将两组查询结果合并。