【问题标题】:Pivot values on column based on grouped columns in SQL基于 SQL 中的分组列在列上透视值
【发布时间】:2017-10-19 02:51:05
【问题描述】:

我想根据组将值转置到列。但是,我事先并不知道这些值。

一个查询给了我这个结果。

Id          Code         EntityId
----------- ------------ -------------
3           22209776     1
4           143687971    3
4           143687971    4
4           143687971    5
4           143687971    15
5           143658155    7
5           143658155    8

我想输出这个

Id          Code         EntityId1     EntityId2     EntityId3     EntityId4
----------- ------------ ------------- ------------- ------------- -------------
3           22209776     1             NULL          NULL          NULL
4           143687971    3             4             5             15
5           143658155    7             8             NULL          NULL

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    如果您现在知道结果中有多少列,则需要使用动态 T-SQL 语句来构建 PIVOT。例如:

    IF OBJECT_ID('tempdb..#DataSource') IS NOT NULL
    BEGIN;
        DROP TABLE #DataSource;
    END;
    
    CREATE TABLE #DataSource
    (
        [id] INT
       ,[Code] INT
       ,[EntityId] INT
    );
    
    DECLARE @DynamicTSQLStatement NVARCHAR(MAX)
           ,@Columns NVARCHAR(MAX);
    
    DECLARE @MaxColumns INT;
    
    INSERT INTO #DataSource ([id], [Code], [EntityId])
    VALUES (3, 22209776 , 1)
          ,(4, 143687971, 3)
          ,(4, 143687971, 4)
          ,(4, 143687971, 5)
          ,(4, 143687971, 15)
          ,(5, 143658155, 7)
          ,(5, 143658155, 8)
          ,(4, 143687971, 25)
          ,(4, 143687971, 26);
    
    -- we need to know how many columns are going to be shown
    SELECT TOP 1 @MaxColumns = COUNT(*)
    FROM #DataSource
    GROUP BY [Code]
    ORDER BY COUNT(*) DESC;
    
    -- we are building here the following string '[1],[2],[3],[4],[5],[6]'; 
    -- this will change depending the input data
    WITH gen AS 
    (
        SELECT 1 AS num
        UNION ALL
        SELECT num+1 
        FROM gen 
        WHERE num+1<=@MaxColumns
    )
    SELECT @Columns = STUFF
    (
        (
            SELECT ',[EntityId' + CAST([num] AS VARCHAR(12)) + ']'
            FROM gen
            FOR XML PATH(''), TYPE
    
        ).value('.', 'VARCHAR(MAX)')
        ,1
        ,1
        ,''
    )
    OPTION (maxrecursion 10000);
    
    SET @DynamicTSQLStatement = N'
    SELECT *
    FROM 
    ( 
        SELECT [id]
              ,[Code]
              ,[EntityId]
              ,''EntityId'' + CAST(ROW_NUMBER() OVER(PARTITION BY [Code] ORDER BY [EntityId]) AS VARCHAR(12))
        FROM #DataSource
    ) DS ([id], [Code], [EntityId], [RowID])
    PIVOT 
    (
        MAX([EntityId]) for [RowID] in (' + @Columns +')
    ) PVT;';
    
    EXEC sp_executesql @DynamicTSQLStatement;
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用枢轴功能:

      declare @tmp TABLE (id int, Code int, EntityId NVARCHAR(10))
      
      insert into @tmp (id, Code, EntityId)
      values  (3, 22209776 , 1),
              (4, 143687971, 3),
              (4, 143687971, 4),
              (4, 143687971, 5),
              (4, 143687971, 15),
              (5, 143658155, 7),
              (5, 143658155, 8)
      
      select 
           pvt.id
          ,pvt.Code
          ,[1] as EntityID1
          ,[2] as EntityID2
          ,[3] as EntityID3
          ,[4] as EntityID4
      from (  
          select 
               id, Code, EntityId
              ,ROW_NUMBER() over(partition by code order by EntityId) as RowNum
      from 
          @tmp
      ) a
      pivot (MAX(EntityId) for RowNum in ([1], [2], [3], [4])) as pvt
      

      【讨论】:

      • 我会尽快尝试的。如果 EntityId 实际上对应于其他地方的名称怎么办。我基本上应该旋转 nvarchar。可能的?基本上做这 MAX(EntityId) 以外的事情,但选择 nvarchar 值。
      • 你能澄清你的意思吗?
      • 我想知道 EntityId 是否可以是 VARCHAR 并且可以。您的答案有效,但是,@gotqn 得到了更好的解释。感谢您的回答!
      猜你喜欢
      • 1970-01-01
      • 2021-07-04
      • 2013-08-04
      • 1970-01-01
      • 2021-06-27
      • 2020-09-16
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多