You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL:如何在SELECT子句中使用多查询实现行转列?

解决行转列(将month转为m1-m4列)的SQL问题

嘿,别着急,你遇到的是典型的**行转列(Pivot)**问题,我来一步步帮你搞定!

首先先明确你的表和数据:
你的aaa表数据整理后如下:

year | month | amount
-----|-------|-------
1991 | 1     | 1.1
1991 | 2     | 1.2
1991 | 3     | 1.3
1991 | 4     | 1.4
1992 | 1     | 2.1
1992 | 2     | 2.2
1992 | 3     | 2.3
1993 | 4     | 2.4  -- 注:原始数据里1993年只有4月的记录

你期望的结果是把每个month的值转为单独的列(m1到m4),按year分组展示。

先说说你之前尝试的SQL问题

  • 第一个SQL的问题:子查询SELECT amount FROM aaa WHERE month=1没有关联外层的year,会返回所有month=1的记录,当有多个值时就会报错“子查询返回多于一行”。
  • 第二个SQL虽然关联了year,但没有用聚合函数,而且GROUP BY year后,外层表的非聚合字段不符合多数数据库的语法规则(比如MySQL的ONLY_FULL_GROUP_BY模式),会直接报错或返回不可预期的结果。

正确的通用解法(适用于绝大多数数据库:MySQL、PostgreSQL、SQLite等)

我们可以用CASE WHEN配合聚合函数(比如MAX(),因为每个year+month组合只有一条数据,MAX和SUM效果一致)来实现行转列:

SELECT 
    year,
    MAX(CASE WHEN month = 1 THEN amount END) AS m1,
    MAX(CASE WHEN month = 2 THEN amount END) AS m2,
    MAX(CASE WHEN month = 3 THEN amount END) AS m3,
    MAX(CASE WHEN month = 4 THEN amount END) AS m4
FROM aaa
GROUP BY year
ORDER BY year;

逻辑解释:

  • CASE WHEN month = 1 THEN amount END:只保留当前行month=1时的amount值,其他情况为NULL
  • MAX():按year分组后,提取每个分组内对应month的非NULL值(每个year对应一个month的记录唯一,MAX会精准拿到目标值,NULL会被忽略)
  • GROUP BY year:按年份分组,把同一年的所有行合并成一行
  • ORDER BY year:让结果按年份排序,和你期望的格式对齐

如果你用的是支持PIVOT语法的数据库(比如SQL Server、Oracle)

也可以用更简洁的PIVOT语法,比如SQL Server的写法:

SELECT year, m1, m2, m3, m4
FROM aaa
PIVOT (
    MAX(amount)
    FOR month IN ([1] AS m1, [2] AS m2, [3] AS m3, [4] AS m4)
) AS PivotTable
ORDER BY year;

最终执行结果

执行通用SQL后,会得到如下结果(和你的期望基本一致,修正了原始数据的笔误):

year | m1  | m2  | m3  | m4
-----|-----|-----|-----|-----
1991 | 1.1 | 1.2 | 1.3 | 1.4
1992 | 2.1 | 2.2 | 2.3 | NULL
1993 | NULL| NULL| NULL| 2.4

内容的提问来源于stack exchange,提问作者Sean.H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:44:38