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

如何基于EmpID将多组Start_Date和End_Date进行Pivot转换?

解决同时转置Start_Date和End_Date为单行多列的问题

核心思路

要同时将每个EmpID对应的多组起止日期转成单行,关键是先给每个EmpID下的任务按顺序编号,再通过条件聚合或动态SQL把每组Start/End配对转成对应的列。


步骤1:给任务生成序号

先通过窗口函数ROW_NUMBER()为每个EmpID的任务分配唯一序号(按TaskID排序,也可根据实际需求更换排序字段):

SELECT 
    EmpID,
    Start_Date,
    End_Date,
    ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
FROM YourTaskTable

方法1:条件聚合(通用所有支持窗口函数的数据库)

如果能确定最大任务数量(比如最多10条),直接用CASE语句按序号筛选对应字段,再聚合:

SELECT
    EmpID,
    -- 第1组任务
    MAX(CASE WHEN TaskSeq = 1 THEN Start_Date END) AS Start1,
    MAX(CASE WHEN TaskSeq = 1 THEN End_Date END) AS End1,
    -- 第2组任务
    MAX(CASE WHEN TaskSeq = 2 THEN Start_Date END) AS Start2,
    MAX(CASE WHEN TaskSeq = 2 THEN End_Date END) AS End2,
    -- 按需扩展到最大任务数,比如到第10组
    MAX(CASE WHEN TaskSeq = 10 THEN Start_Date END) AS Start10,
    MAX(CASE WHEN TaskSeq = 10 THEN End_Date END) AS End10
FROM (
    SELECT 
        EmpID,
        Start_Date,
        End_Date,
        ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
    FROM YourTaskTable
) AS TaskWithSeq
GROUP BY EmpID

这里用MAX是因为每个序号对应唯一一条记录,聚合后只会保留对应的值,MIN也能达到同样效果。


方法2:动态SQL(适配任务数量不固定的场景)

如果任务数量不固定,用动态SQL自动生成所有需要的列,以下是不同数据库的实现:

SQL Server版本

-- 获取最大任务序号
DECLARE @MaxSeq INT
SELECT @MaxSeq = MAX(TaskSeq)
FROM (
    SELECT ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
    FROM YourTaskTable
) AS Seq

-- 生成列定义
DECLARE @Cols NVARCHAR(MAX) = ''
SELECT @Cols = @Cols + 
    ', MAX(CASE WHEN TaskSeq = ' + CAST(Seq AS VARCHAR) + ' THEN Start_Date END) AS Start' + CAST(Seq AS VARCHAR) +
    ', MAX(CASE WHEN TaskSeq = ' + CAST(Seq AS VARCHAR) + ' THEN End_Date END) AS End' + CAST(Seq AS VARCHAR)
FROM (
    SELECT DISTINCT TaskSeq
    FROM (
        SELECT ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
        FROM YourTaskTable
    ) AS Seq
) AS DistinctSeq
ORDER BY Seq

-- 拼接并执行最终SQL
DECLARE @FinalSQL NVARCHAR(MAX) = '
SELECT EmpID' + @Cols + '
FROM (
    SELECT 
        EmpID,
        Start_Date,
        End_Date,
        ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
    FROM YourTaskTable
) AS TaskWithSeq
GROUP BY EmpID
'

EXEC sp_executesql @FinalSQL

MySQL版本

-- 获取最大任务序号
SELECT MAX(TaskSeq) INTO @MaxSeq
FROM (
    SELECT ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
    FROM YourTaskTable
) AS Seq;

-- 生成列定义
SET @Cols = '';
SELECT GROUP_CONCAT(
    CONCAT(
        'MAX(CASE WHEN TaskSeq = ', Seq, ' THEN Start_Date END) AS Start', Seq, ',',
        'MAX(CASE WHEN TaskSeq = ', Seq, ' THEN End_Date END) AS End', Seq
    )
) INTO @Cols
FROM (
    SELECT DISTINCT TaskSeq
    FROM (
        SELECT ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
        FROM YourTaskTable
    ) AS Seq
) AS DistinctSeq
ORDER BY Seq;

-- 拼接并执行最终SQL
SET @FinalSQL = CONCAT('
SELECT EmpID, ', @Cols, '
FROM (
    SELECT 
        EmpID,
        Start_Date,
        End_Date,
        ROW_NUMBER() OVER(PARTITION BY EmpID ORDER BY TaskID) AS TaskSeq
    FROM YourTaskTable
) AS TaskWithSeq
GROUP BY EmpID
');

PREPARE stmt FROM @FinalSQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

动态SQL会自动根据实际存在的任务序号生成对应的StartN和EndN列,无需手动维护列数量。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:03:21