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

如何将同一张表中的列转置为行?

解决方案:SQL列转行(Unpivoting)实现

这是典型的**列转行(Unpivoting)**需求,目的是把原表中多个同类型的列(Dept1/Dept2/Dept3)转换成多行记录。下面提供几种适配不同数据库的实现方式:

1. 通用方案:使用UNION ALL(支持所有SQL数据库)

这种方法兼容性最强,几乎所有数据库都支持,逻辑也直白易懂:

SELECT EmployeeId, Dept1 AS Dept
FROM Employee_History
WHERE Dept1 IS NOT NULL -- 可选:过滤空值,不需要可以删除该行
UNION ALL
SELECT EmployeeId, Dept2 AS Dept
FROM Employee_History
WHERE Dept2 IS NOT NULL
UNION ALL
SELECT EmployeeId, Dept3 AS Dept
FROM Employee_History
WHERE Dept3 IS NOT NULL;

说明:

  • 使用UNION ALL而非UNION:前者不会自动去重,性能更高,符合我们保留所有有效部门记录的需求;如果你的场景需要去重,可以替换为UNION。
  • WHERE子句是可选的,如果允许部门值为空,可以直接去掉。

2. 专用语法:UNPIVOT(适用于SQL Server、Oracle等支持该语法的数据库)

如果你的数据库支持原生UNPIVOT语法,用这种方式更简洁:

SELECT EmployeeId, Dept
FROM Employee_History
UNPIVOT (
    Dept FOR DeptColumns IN (Dept1, Dept2, Dept3)
) AS UnpivotResult;

说明:

  • Dept是转置后生成的新列名,对应原表中的部门值;
  • DeptColumns是临时生成的列(我们不需要它,所以查询时没选),用来存储原表的列名(比如Dept1/Dept2/Dept3);
  • 该语法会自动过滤空值,不需要额外写WHERE条件。

3. MySQL 专属方案(无原生UNPIVOT时)

MySQL没有原生的UNPIVOT,除了用上面的UNION ALL,还可以用CROSS JOIN结合CASE的方式实现:

SELECT 
    eh.EmployeeId,
    CASE num.dept_idx
        WHEN 1 THEN eh.Dept1
        WHEN 2 THEN eh.Dept2
        WHEN 3 THEN eh.Dept3
    END AS Dept
FROM Employee_History eh
CROSS JOIN (
    SELECT 1 AS dept_idx UNION ALL 
    SELECT 2 UNION ALL 
    SELECT 3
) num
WHERE CASE num.dept_idx
        WHEN 1 THEN eh.Dept1
        WHEN 2 THEN eh.Dept2
        WHEN 3 THEN eh.Dept3
    END IS NOT NULL;

说明:

  • 这里通过CROSS JOIN生成3行临时记录,配合CASE语句把原表的列值依次取出来,最终实现列转行;
  • 同样,WHERE子句用来过滤空值,不需要可以删除。

针对你的测试数据,以上三种方法都能得到你预期的输出结果:

EmployeeId Dept
150        10
150        55
150        6

内容的提问来源于stack exchange,提问作者Martin James

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:09:06