如何在SSMS中使用T-SQL将单列日期按工单转换为多列日期
T-SQL 动态行转列实现方案
你描述的需求实际是**动态PIVOT(行转列)**操作(UNPIVOT是列转行,和你的目标方向相反),不需要提前预知每个工单的更新日期数量,也不会破坏你已经用row_number()排好的顺序,具体实现逻辑和代码如下:
实现逻辑
- 因为你已经通过
row_number() over(partition by ticket ...)给每个工单下的更新日期生成了连续且唯一的序号rownum,直接基于这个序号做动态行转列即可 - 由于每个(ticket, rownum)组合只对应唯一一条日期记录,PIVOT语法要求的聚合函数仅做语法占位,不会实际触发多值聚合计算
- 动态拼接列名时按rownum升序排列,保证最终输出的Dt1、Dt2...列顺序和你预设的排序完全一致,列总数自动适配全表工单的最大更新次数
可直接运行的代码
首先假设你的原表名为ticket_update,你可以替换成自己的实际表名:
-- 若需要复现样例数据,可先执行以下建表插数语句 -- CREATE TABLE ticket_update ( -- rownum INT, -- ticket INT, -- updated DATE -- ) -- INSERT INTO ticket_update VALUES -- (1,1,'2022-01-01'), -- (2,1,'2022-01-03'), -- (1,2,'2022-01-27'), -- (1,3,'2022-03-01'), -- (2,3,'2022-04-02'), -- (3,3,'2022-05-03'), -- 原样例此处笔误写为3/1/2022,对应目标表第三列5/3/2022 -- (1,4,'2022-07-11') DECLARE @cols NVARCHAR(MAX), @pivot_cols NVARCHAR(MAX), @sql NVARCHAR(MAX) -- 自动生成所有需要的日期列,适配任意数量的更新次数 -- SQL Server 2017及以上版本用STRING_AGG拼接 SELECT @cols = STRING_AGG('[' + CAST(rownum AS VARCHAR(10)) + '] AS Dt' + CAST(rownum AS VARCHAR(10)), ',') WITHIN GROUP (ORDER BY rownum), @pivot_cols = STRING_AGG('[' + CAST(rownum AS VARCHAR(10)) + ']', ',') WITHIN GROUP (ORDER BY rownum) FROM (SELECT DISTINCT rownum FROM ticket_update) t -- 低版本SQL Server(2016及以下)用下面的FOR XML PATH逻辑替换上面的列拼接即可 -- SELECT -- @cols = STUFF((SELECT ',[' + CAST(rownum AS VARCHAR(10)) + '] AS Dt' + CAST(rownum AS VARCHAR(10)) FROM (SELECT DISTINCT rownum FROM ticket_update) t ORDER BY rownum FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,1,''), -- @pivot_cols = STUFF((SELECT ',[' + CAST(rownum AS VARCHAR(10)) + ']' FROM (SELECT DISTINCT rownum FROM ticket_update) t ORDER BY rownum FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'') -- 拼接最终查询语句 SET @sql = ' SELECT ticket, ' + @cols + ' FROM ticket_update PIVOT ( MAX(updated) -- 仅为PIVOT语法要求占位,无实际聚合计算 FOR rownum IN (' + @pivot_cols + ') ) p ORDER BY ticket' -- 执行查询得到结果 EXEC sp_executesql @sql
效果说明
- 执行后输出的列数会自动匹配全表工单的最大更新次数,不需要手动修改代码
- 每个工单下的日期严格按照你预先用
row_number()生成的顺序横向排列,更新日期不足的工单对应Dt列会返回空值,和你给出的目标表结构完全一致 - 因为没有额外的分组、排序逻辑,查询性能和直接查询原表基本一致
内容的提问来源于stack exchange,提问作者Compass
相关产品推荐
相关产品推荐

