【问题标题】:SQL Server Pivot Data without aggregation没有聚合的 SQL Server Pivot Data
【发布时间】:2019-07-03 17:24:54
【问题描述】:

我知道这已经被问过很多次了,但我很难找到我需要的解决方案。

数据:

Id   FKId   TypeId   Score   ScoreDate
1    317    1        90      2019-01-01
2    317    1        80      2019-01-02
3    317    2        65      2019-01-03
4    317    2        80      2019-01-04
5    318    1        82      2019-01-01
6    318    1        78      2019-01-02
7    318    2        55      2019-01-03
8    318    2        63      2019-01-04

预期结果:

FkId   A1   A2   B1  B2
317    90   80   65  80
318    82   78   55  63

我尝试使用枢轴来获取数据,但我偶然发现的是您需要使用聚合函数,这会导致错误的结果。其中一种尝试的示例:

select *
from 
(
  select [FkId], [TypeId], [Score]
  from #yt
) src
pivot
(
  max([Score])
  for [TypeId] in ([1], [2], [3])
) piv;

query result:
FkId  1     2       3
101   83    82  NULL
102   96    80  NULL

我知道我需要不止一个查询才能获得预期结果,但这不是我关心的问题,现在我只想将一种类型的分数与每个分数转置到它自己的列中。

任何帮助都可以。

【问题讨论】:

    标签: sql-server tsql dynamic pivot


    【解决方案1】:

    试试这个:

    CREATE TABLE #yt
    (
        [Id] INT
       ,[FKId] INT
       ,[TypeId] TINYINT
       ,[Score] INT
       ,[ScoreDate] DATE
    )
    
    INSERT INTO #yt
    VALUES (1, 317, 1, 90, '2019-01-01')
          ,(2, 317, 1, 80, '2019-01-02')
          ,(3, 317, 2, 65, '2019-01-03')
          ,(4, 317, 2, 80, '2019-01-04')
          ,(5, 318, 1, 82, '2019-01-01')
          ,(6, 318, 1, 78, '2019-01-02')
          ,(7, 318, 2, 55, '2019-01-03')
          ,(8, 318, 2, 63, '2019-01-04');
    
    select *
    from 
    (
        SELECT [FKId]
            ,CHAR(64 + DENSE_RANK() OVER (PARTITION BY FKID ORDER BY TypeID)) + CAST(DENSE_RANK() OVER (PARTITION BY FKID, TypeID ORDER BY [ScoreDate]) AS VARCHAR(12))
            ,[Score]
        FROM #yt
    ) src ([FKId], [TypeID], [Score])
    pivot
    (
      max([Score])
      for [TypeId] in ([A1], [A2], [B1], [B2])
    ) piv;
    
    
    DROP TABLE #yt;
    

    或者如果你想让它动态化:

    DECLARE @DynamicTSQLStatement NVARCHAR(MAX)
           ,@DynamicColumns NVARCHAR(MAX)
    
    SET @DynamicColumns = STUFF
                            (
                                (
                                    SELECT DISTINCT ',[' + CHAR(64 + DENSE_RANK() OVER (PARTITION BY FKID ORDER BY TypeID)) + CAST(DENSE_RANK() OVER (PARTITION BY FKID, TypeID ORDER BY [ScoreDate]) AS VARCHAR(12)) + ']'
                                    FROM #yt                               
                                    FOR XML PATH('') ,TYPE
                                ).value('.', 'NVARCHAR(MAX)')
                                ,1
                                ,1
                                ,''
                            );
    
    SET @DynamicTSQLStatement = N'
    select *
    from 
    (
        SELECT [FKId]
            ,CHAR(64 + DENSE_RANK() OVER (PARTITION BY FKID ORDER BY TypeID)) + CAST(DENSE_RANK() OVER (PARTITION BY FKID, TypeID ORDER BY [ScoreDate]) AS VARCHAR(12))
            ,[Score]
        FROM #yt
    ) src ([FKId], [TypeID], [Score])
    pivot
    (
      max([Score])
      for [TypeId] in ('+@DynamicColumns+')
    ) piv;'
    
    
    EXEC sp_executesql @DynamicTSQLStatement;
    

    【讨论】:

      【解决方案2】:

      检查一下:我使用了两个查询,然后将它们合并并取其最大值

      CREATE TABLE t (
        "Id" INTEGER,
        "FKId" INTEGER,
        "TypeId" INTEGER,
        "Score" INTEGER,
        "ScoreDate" date
      );
      
      
      GO
      
      INSERT INTO t
        ("Id", "FKId", "TypeId", "Score", "ScoreDate")
      VALUES
        ('1', '317', '1', '90', '2019-01-01'),
        ('2', '317', '1', '80', '2019-01-02'),
        ('3', '317', '2', '65', '2019-01-03'),
        ('4', '317', '2', '80', '2019-01-04'),
        ('5', '318', '1', '82', '2019-01-01'),
        ('6', '318', '1', '78', '2019-01-02'),
        ('7', '318', '2', '55', '2019-01-03'),
        ('8', '318', '2', '63', '2019-01-04');
      GO
      
      受影响的 8 行
      select [FkId], max([1]) as c1, max([2]) as c2, max([3]) as c3, max([4]) as c4 from
      (
      select FkId, [1], [2], [3], [4] from
      (
        select *
        from
        (
          select [FkId], [TypeId], [Score]
          from t
        ) src
        pivot
        (
          max([Score])
          for [TypeId] in ([1], [2] , [3], [4])
        ) as Piv1
      ) P
      union all
      select FkId, null, null, [1], [2] from
      (
        select *
        from
        (
          select [FkId], [TypeId], [Score]
          from t
        ) src
        pivot
        (
          min([Score])
          for [TypeId] in ( [1], [2])
        ) as Piv2
      ) P2
      ) PP
      group by FkId
      GO
      
      FkId | c1 | c2 | c3 | c4 ---: | -: | -: | -: | -: 317 | 90 | 80 | 80 | 65 318 | 82 | 63 | 78 | 55

      db小提琴here

      【讨论】:

        猜你喜欢
        • 2013-03-24
        • 2012-02-20
        • 1970-01-01
        • 2016-10-16
        • 2014-12-30
        • 1970-01-01
        • 2010-11-17
        • 2020-06-22
        • 2018-12-11
        相关资源
        最近更新 更多