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

如何在SQL中将周期列转行,实现每个周期对应一行记录

高效实现宽表转窄表(行转列)的SQL方案

方案1:使用UNPIVOT(适用于SQL Server、Oracle等支持该语法的数据库)

这是数据库原生支持的行转列语法,优化器能更好地处理执行逻辑,性能远优于多次UNION ALL,尤其适合数据量较大的场景。

假设你的表名为employee_salary,执行以下SQL:

SELECT 
    Code,
    Name,
    Period,
    Salary
FROM 
    employee_salary
UNPIVOT (
    Salary FOR Period IN (
        [Period 1],
        [Period 2],
        [Period 3]
    )
) AS unpvt;

执行后每个员工的各周期薪资会自动拆分为独立行,比如Worker 5会生成3条分别对应Period 1、Period 2、Period 3的记录,薪资均为5000。

方案2:使用CROSS JOIN配合值列表(适用于MySQL、PostgreSQL等无UNPIVOT的数据库)

如果你的数据库不支持UNPIVOT,这种方式比手动多次UNION ALL更简洁,执行效率也相当:

MySQL版本

SELECT 
    es.Code,
    es.Name,
    p.period_name AS Period,
    CASE p.period_name
        WHEN 'Period 1' THEN es.`Period 1`
        WHEN 'Period 2' THEN es.`Period 2`
        WHEN 'Period 3' THEN es.`Period 3`
    END AS Salary
FROM 
    employee_salary es
CROSS JOIN (
    SELECT 'Period 1' AS period_name UNION ALL
    SELECT 'Period 2' UNION ALL
    SELECT 'Period 3'
) p;

PostgreSQL版本

SELECT 
    es.Code,
    es.Name,
    p.period_name AS Period,
    CASE p.period_name
        WHEN 'Period 1' THEN es."Period 1"
        WHEN 'Period 2' THEN es."Period 2"
        WHEN 'Period 3' THEN es."Period 3"
    END AS Salary
FROM 
    employee_salary es
CROSS JOIN (
    UNNEST(ARRAY['Period 1', 'Period 2', 'Period 3']) AS period_name
) p;

额外优化

如果不需要保留薪资为0的记录,可在语句末尾添加WHERE Salary > 0过滤无效数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:55:46