【问题标题】:How to Pivot on two columns in SQL Server [duplicate]如何在 SQL Server 中的两列上进行透视[重复]
【发布时间】:2018-12-13 10:49:21
【问题描述】:

以下是我拥有的数据行:

ID     Code      OtherCol
7      Code1      NULL
7      code2      NULL
2      unk        NULL
4      unk        NULL
3      Code2      NULL
3      Code3      NULL
3      Code5      Other1
5      Code4      NULL
5      Code5      Other2

我正在尝试将其显示为

ID name1 name2 name3 name4 name5 nameunk Othername
2                                unk
3        code2 code3       code5         Other1
4                                unk                    
5                    code4 code5         Other2
7  code1 code2

我能够旋转第一列,但旋转第二列时出现问题。

对于给定的code,还有一个name,但OtherCol 下的值是随机的。

【问题讨论】:

  • 欢迎来到SO,但你的问题不清楚,name1name5 是什么?我想code1 显示在name1 下,所以它对应于代码,但为什么code4 显示在name5 下?您要转置多少个唯一值?如果给定 ID 的 unk 值出现两次会怎样?
  • 感谢您指出,这是错误的。对于给定的 ID,“unk”只会发生一次
  • 只是给一些比赛一个 ID 可以有从 Code1 到 Code5 的任何代码,包括对应于给定名称的“unk”(未知),唯一的扭曲是有时 ID 可以有完全随机的值(code5 标识“ other value' 和附加列 'OtherCol' 以捕获相应的值)以及任何其他代码,希望对您有所帮助

标签: sql sql-server tsql pivot multiple-columns


【解决方案1】:

我推荐条件聚合:

select id,
       max(case when code = 'code1' then code end) as name1,
       max(case when code = 'code2' then code end) as name2,
       max(case when code = 'code3' then code end) as name3,
       max(case when code = 'code4' then code end) as name4,
       max(case when code = 'code5' then code end) as name5,
       max(case when code = 'unk' then code end) as nameunk,
       max(othercol) as othercol
from t
group by id;

【讨论】:

    【解决方案2】:

    这是完整的工作示例。您可以稍微更改一下以匹配您的真实数据。

    CREATE TABLE #DataSource
    (
        [ID] INT
       ,[Code] VARCHAR(12)
       ,[OtherCol] VARCHAR(12)
    );
    
    INSERT INTO #DataSource ([ID], [Code], [OtherCol])
    VALUES (7, 'Code1', NULL)
          ,(7, 'code2', NULL)
          ,(2, 'Unk', NULL)
          ,(4, 'Unk', NULL)
          ,(3, 'Code2', NULL)
          ,(3, 'Code3', NULL)
          ,(3, 'Code5', 'Other1')
          ,(5, 'Code4', NULL)
          ,(5, 'Code4', 'Other2');
    
    
    DECLARE @DynammicTSQLStatement NVARCHAR(MAX)
           ,@DynamicPIVOTColumns NVARCHAR(MAX);
    
    
    SET @DynamicPIVOTColumns = STUFF
                              (
                                    (
                                    SELECT ',[' + CAST([value] AS VARCHAR(12)) + ']'
                                    FROM 
                                    (
                                        SELECT 0
                                             ,DENSE_RANK() OVER (ORDER BY [Code])
                                             ,REPLACE([Code], 'Code', 'name')
                                        FROM #DataSource
                                        WHERE [Code] IS NOT NULL
                                        UNION
                                        SELECT 1
                                              ,1
                                              ,'OtherCol'
                                    ) DS ([GroupID],[RowID], [value])
                                    ORDER BY [GroupID], [RowID]
                                    FOR XML PATH('') ,TYPE
                                    ).value('.', 'NVARCHAR(MAX)')
                                    ,1
                                    ,1
                                    ,''
                              );
    
    SET @DynammicTSQLStatement = N'
    SELECT *
    FROM
    (
        SELECT [ID]
              ,[Code]
              ,REPLACE([Code], ''Code'', ''name'')
        FROM #DataSource
        UNION ALL
        SELECT [ID]
              ,[OtherCol]
              ,''OtherCol''
        FROM #DataSource
    ) DS ([ID], [value], [column])
    PIVOT
    (
        MAX([value]) FOR [column] IN (' + @DynamicPIVOTColumns + ')
    ) PVT';
    
    EXEC sp_executesql @DynammicTSQLStatement;
    
    DROP TABLE #DataSource;
    

    【讨论】:

    • 感谢哥们的帮助,试图了解如何避免动态 SQL,因为我必须将此最终表调用到另一个视图中
    • @Kumar2127 如果您的列是静态的:D 只需添加 SELECT @DynammicTSQLStatement 并在您的视图中使用该语句 :-) 好吗?
    【解决方案3】:
    --PIVOT THE TABLE
    select ID,[code1],[code2], [code3],[code4],[code5],[Unk]
    into #resPivot
    from 
    (
      select ID, code
      from tblTest
    ) src
    pivot
    (
      max(code)
      for code in ([code1], [code2], [code3],[code4],[code5],[Unk])
    ) piv;
    
    --FIND ALL COLS WHERE OTHER COLUMN have value row 3,5 in your example
    SELECT * INTO #distinct FROM tblTest where tblTest.otherCol IS NOT NULL
    
    --PIVOTED RESULT WITH ABOVE TABLE
    select distinct #resPivot.ID,[code1], [code2], [code3],[code4],[code5],[Unk],#distinct.otherCol
    into #otherCol
    from #resPivot  inner join #distinct
    on #distinct.id = #resPivot.id 
    
    --THIS IS PIVOTED RESULT WITH ALL RESULTS THAT HAS NO OTHER COL VALUE UNION with OTHER CALL VALUE 
    select distinct #resPivot.ID,[code1], [code2], [code3],[code4],[code5],[Unk],tblTest.otherCol 
    from #resPivot  inner join tblTest
    on tblTest.id = #resPivot.id 
    WHERE otherCol IS NULL and tblTest.ID NOT IN (SELECT ID FROM #otherCol)
    UNION ALL
    Select * from #otherCol
    
    --DROP TEMP TABLES
    Drop Table #resPivot
    Drop Table #distinct
    Drop Table #otherCol
    

    更简单更快的版本

    【讨论】:

      猜你喜欢
      • 2019-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多