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

如何将同一主键的多行数据转行成多列?Pivot实现求助

嘿,我完全懂你的困扰!你现在需要把原本按行展示的不同t3.description对应的金额,转成列来和t1.id、t1.name放在同一行,也就是典型的行转列需求,而且因为t3.description的取值不固定,静态Pivot确实不好用,我来给你一步步拆解解决方案:

先理解静态Pivot(适合已知固定列的情况)

如果暂时你知道所有可能的t3.description取值,可以先用静态Pivot来实现,这样能帮你快速理解Pivot的核心逻辑:

SELECT 
    t1.id,
    t1.name,
    [TEST DESC. 1],
    [TEST DESC. 2]
FROM (
    -- 这里是你的基础查询,先获取需要转置的原始数据
    SELECT 
        t1.id,
        t1.name,
        t3.description,
        t3.amount
    FROM table1 (nolock) t1 
    JOIN table2 (nolock) t2 ON t1.t2_id = t2.id 
    JOIN table3 (nolock) t3 ON t2.t3_id = t3.id
) AS SourceData
PIVOT (
    MAX(amount)  -- 因为每个(id, description)对应唯一金额,用MAX/AVG/SUM都可以,这里选MAX
    FOR description IN ([TEST DESC. 1], [TEST DESC. 2])  -- 指定要转成列的description值
) AS PivotTable;

这个查询会把你指定的description值作为列名,对应的amount填充到列里,就能得到你想要的结果格式。但问题是如果有新的description出现,你就得手动修改IN里的列表,所以接下来给你适配动态列的方案。

动态Pivot(适配不固定的t3.description取值)

这个方案会自动获取所有不同的t3.description值,动态生成列名,完全不需要手动维护:

DECLARE @PivotColumns NVARCHAR(MAX);
DECLARE @DynamicSQL NVARCHAR(MAX);

-- 第一步:动态获取所有不同的description,拼接成带方括号的列名字符串
SELECT @PivotColumns = STRING_AGG(QUOTENAME(description), ', ')
FROM (
    SELECT DISTINCT t3.description
    FROM table1 (nolock) t1 
    JOIN table2 (nolock) t2 ON t1.t2_id = t2.id 
    JOIN table3 (nolock) t3 ON t2.t3_id = t3.id
) AS UniqueDescriptions;

-- 第二步:构建动态SQL语句
SET @DynamicSQL = N'
SELECT 
    id,
    name,
    ' + @PivotColumns + N'
FROM (
    -- 这里替换成你实际的复杂查询即可
    SELECT 
        t1.id,
        t1.name,
        t3.description,
        t3.amount
    FROM table1 (nolock) t1 
    JOIN table2 (nolock) t2 ON t1.t2_id = t2.id 
    JOIN table3 (nolock) t3 ON t2.t3_id = t3.id
) AS SourceData
PIVOT (
    MAX(amount)
    FOR description IN (' + @PivotColumns + N')
) AS PivotTable;';

-- 执行动态生成的SQL
EXEC sp_executesql @DynamicSQL;
几个关键注意点
  • 关于STRING_AGG:这个函数是SQL Server 2017及以上版本支持的,如果你的版本更早,可以用FOR XML PATH来拼接列名,替换第一步的代码:
    SELECT @PivotColumns = STUFF((
        SELECT ', ' + QUOTENAME(description)
        FROM (SELECT DISTINCT t3.description FROM table1 (nolock) t1 JOIN table2 (nolock) t2 ON t1.t2_id = t2.id JOIN table3 (nolock) t3 ON t2.t3_id = t3.id) AS UniqueDescriptions
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '');
    
  • 聚合函数的选择:这里用MAX(amount)是因为每个(id, description)组合应该只有一个金额值,用MAX、MIN、SUM(因为只有一个值,结果一样)都可以,如果你有重复的组合,根据业务需求选择合适的聚合函数即可。
  • 复杂查询适配:只需要把动态SQL里的基础查询部分替换成你实际的复杂查询就行,逻辑完全通用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:59:56