Сводные данные SQL Server без агрегирования - PullRequest
0 голосов
/ 09 февраля 2019

Я знаю, что об этом спрашивали много, много раз, но я изо всех сил пытаюсь найти решение, которое мне нужно.

Данные:

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

Я понимаю, что мне потребуется более одного запроса, чтобы получить ожидаемый результат, но это не мое дело, сейчас я просто хочу перенести одинтип счета с каждым счетом в своем собственном столбце.

Любая помощь будет.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Проверьте это: я использовал два запроса, затем объединил их и взял максимум его значений

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 rows affected
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

дБ <> скрипка здесь

0 голосов
/ 09 февраля 2019

Попробуйте:

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;
...