当前位置: 首页 > news >正文

【MYSQL 】SQL 行列转换实战:如何用 CASE WHEN 与 SUM/MAX 重塑部门表

SQL 行列转换实战:如何用 CASE WHEN 与 SUM/MAX 重塑部门表

一道经典的 SQL 题目,带你彻底理解 GROUP BY 与聚合函数的默契配合


一、问题背景:部门表的重构需求

我们有一张名为 Department 的表,结构如下:

idrevenuemonth
18000Jan
17000Feb
29000Jan
28000Feb

我们希望将这张表从“行存储”转换为“列存储”,即每个部门一行,每个月一列,效果如下:

idJanFebMarDec
180007000
290008000

二、解决方案:CASE WHEN + 聚合函数

✅ 推荐写法(跨数据库通用)

SELECTid,SUM(CASE WHEN month = 'Jan' THEN revenue END) AS Jan_Revenue,SUM(CASE WHEN month = 'Feb' THEN revenue END) AS Feb_Revenue,-- … 依次写出 12 个月SUM(CASE WHEN month = 'Dec' THEN revenue END) AS Dec_Revenue
FROM Department
GROUP BY id
ORDER BY id;

三、理解行列转换的核心逻辑

在这里插入图片描述


四、为什么一定要用聚合函数?

❓ 问题:为什么 GROUP BY 之后必须用 MAX/SUM?

:SQL 规定:GROUP BY 之后,SELECT 中的每一列要么在 GROUP BY 中,要么被聚合函数包裹。

📌 举例说明:

原始数据:

idmonthrevenue
1Jan8000
1Feb7000

如果你写:

SELECT id, revenue
FROM Department
GROUP BY id; -- 错误!

数据库不知道 revenue 该显示 8000 还是 7000。


五、MAX 还是 SUM?如何选择?

聚合函数作用适用场景
MAX取最大值每月只有一行时,效果与 SUM 相同
SUM求和更健壮,可处理重复数据
COUNT计数❌ 错误!会返回行数,不是收入值

✅ 推荐使用 SUM:

  • 语义更清晰:我们是在“汇总”收入,不是“取最大”
  • 容错性更强:即使有重复数据,也能正确累加

六、图解“压行”过程(以 id=1 为例)

步骤数据状态说明
原始数据(1, 8000, Jan)
(1, 7000, Feb)
两行记录
CASE WHEN 后(1, 8000, NULL)
(1, NULL, 7000)
月份拆成列
GROUP BY + SUM(1, 8000, 7000)多行合并为一行

七、常见问题解答(FAQ)

❓ 为什么 MAX 可以“保留值”而不是取最大?

因为每个 id 下每个月只有一行,MAX 实际上只作用在一个非 NULL 值上,相当于“提取唯一值”。

❓ 可以不加 ORDER BY 吗?

可以。ORDER BY 只是为了结果美观,不是语法必需。

❓ 如果一个月有多个收入记录怎么办?

使用 SUM 会自动累加,而 MAX 只会保留其中一个值。


八、总结

  • 使用 CASE WHEN 将行转为列
  • 使用 SUM/MAX 配合 GROUP BY 将多行合并为一行
  • SUM 更健壮,MAX 更“纯粹”,根据需求选择
  • 记住:聚合函数在 GROUP BY 中是“压行工具人”

九、完整代码示例

SELECTid,SUM(CASE WHEN month = 'Jan' THEN revenue END) AS Jan_Revenue,SUM(CASE WHEN month = 'Feb' THEN revenue END) AS Feb_Revenue,SUM(CASE WHEN month = 'Mar' THEN revenue END) AS Mar_Revenue,SUM(CASE WHEN month = 'Apr' THEN revenue END) AS Apr_Revenue,SUM(CASE WHEN month = 'May' THEN revenue END) AS May_Revenue,SUM(CASE WHEN month = 'Jun' THEN revenue END) AS Jun_Revenue,SUM(CASE WHEN month = 'Jul' THEN revenue END) AS Jul_Revenue,SUM(CASE WHEN month = 'Aug' THEN revenue END) AS Aug_Revenue,SUM(CASE WHEN month = 'Sep' THEN revenue END) AS Sep_Revenue,SUM(CASE WHEN month = 'Oct' THEN revenue END) AS Oct_Revenue,SUM(CASE WHEN month = 'Nov' THEN revenue END) AS Nov_Revenue,SUM(CASE WHEN month = 'Dec' THEN revenue END) AS Dec_Revenue
FROM Department
GROUP BY id;
http://www.dtcms.com/a/423521.html

相关文章:

  • 网站申请支付宝支付网站关键词选取的方法
  • 最新版谷歌浏览器Axure插件(免翻墙)
  • 网站加载特效代码开源镜像网站开发
  • 虚拟串口工具vspd
  • 从入门到精通【Redis】理解Redis事务
  • Android16 wifi启动后自动连接的第一个wifi分析和修改
  • 【C++STL :vector类 (一) 】详解vector类的使用层vector实践:算法题练习
  • 做淘宝用那些网站发货如何进行电子商务网站推广
  • 语言是火,视觉是光:论两种智能信号的宿命与人机交互的未来
  • Java应用实例:三角形判断(向量叉积、海伦公式)、分数序列求和
  • Go Modules 包管理 (Go 模块)
  • Go基础(⑦实例和依赖注入)
  • 网站建设绩效考核方案ppt网页开发背景与意义
  • 【数据结构】基础知识
  • Fluttercon EU 2025 :Let‘s go far with Flutter
  • go-commons/stringutils 与标准库 strings 对比
  • 长春网站推广方式seo综合查询国产
  • 探索3D空间的视觉基础模型系列
  • 自建营销型企业网站怎么建设公益网站
  • C# 基于halcon的视觉工作流-章40-OCR训练识别
  • OCR API-智能文字识别技术,从“手动录入”到“智慧识别”的跨越
  • 收到网站代码后怎么做设计素材模板
  • JWT (JSON Web Token) 综合指南
  • 【笔记】在WPF中Binding里的详细功能介绍
  • html 滚动条相关开发经验总结
  • C++基础:(六) 内存管理深度解析:从分布到实现
  • BUUCTF get_started_3dsctf_2016 wp
  • 成都网站制作设计网页设计实训报告心得体会
  • Linux 进程创建与控制详解
  • 万网x3主机l系统放两个网站手机制作ppt