Конвертировать строки в N столбцов в SQL Server - PullRequest
0 голосов
/ 15 мая 2019

Мне нужно преобразовать этот набор данных в строки

ID  year    reading writing spelling
33087   7   625 620 686
33087   8   544 560 541
33205   7   559 572 497
33205   8   599 560 612
33902   7   500 484 464
33902   8   607 560 686

в это:

ID  year    reading writing spelling year   reading writing spelling 
33087   7   625     620     686      8      544     560     541
33205   7   559     572     497      8      599     560     612
33902   7   500     484     464      8      607     560     686

Это мой код:

select * from 
(select ID,year,reading 
       from #Table1 NP 
JOIN #table2 CS  ON CS.Id = NP.ID
) as  src
PIVOT
(
sum(reading) for year in ([7],[8])
) as piv 

Я не уверен, как получить остальные строки в столбцах.

Ответы [ 3 ]

0 голосов
/ 15 мая 2019

Используя самостоятельное соединение, мы можем получить результат, попробуйте

;WITH CTE(ID ,[year],reading, writing, spelling)
AS
(
SELECT 33087,7,625,620,686 UNION ALL
SELECT 33087,8,544,560,541 UNION ALL
SELECT 33205,7,559,572,497 UNION ALL
SELECT 33205,8,599,560,612 UNION ALL
SELECT 33902,7,500,484,464 UNION ALL
SELECT 33902,8,607,560,686      
)
SELECT i.ID ,i.[year],i.reading, i.writing, i.spelling,
            o.[year],o.reading, o.writing, o.spelling
FROM CTE i
INNER JOIN CTE o 
    ON i.ID = o.ID
WHERE i.[year] =7 
    AND o.[year] =8

Результат

ID      year    reading writing spelling    year    reading writing spelling
-----------------------------------------------------------------------------
33087   7         625    620      686         8       544      560    541
33205   7         559    572      497         8       599      560    612
33902   7         500    484      464         8       607      560    686
0 голосов
/ 15 мая 2019

Этот код организует данные для каждого идентификатора в одну строку.Столбцы будут упорядочены по годам, и каждый год будет отображаться под каждым номером для каждого идентификатора.Если год для идентификатора пуст, он будет заполнен значениями NULL.В результирующих столбцах будут перечислены только годы, которые встречаются в наборе данных.

DECLARE @sql AS NVARCHAR(MAX)
DECLARE @pc AS NVARCHAR(20)
DECLARE @column_list AS NVARCHAR(MAX) 

SELECT  @pc = CONVERT(NVARCHAR, PIVOT_CODE),
        @column_list = COALESCE(@column_list + ',', '') + ' year' + @pc + ', reading' + @pc + ', writing' +@pc + ', spelling' + @pc
FROM (    
    SELECT DISTINCT Year AS PIVOT_CODE FROM YourTable 
) AS DistYears
ORDER BY PIVOT_CODE

SET @sql = '
;WITH p AS (
    SELECT ID,''year'' + CAST(year AS NVARCHAR(10)) AS Col, year AS Val FROM YourTable
    UNION ALL
    SELECT ID,''reading'' + CAST(year AS NVARCHAR(10)) AS Col, reading AS Val FROM YourTable
    UNION ALL
    SELECT ID,''writing'' + CAST(year AS NVARCHAR(10)) AS Col, writing AS Val FROM YourTable
    UNION ALL
    SELECT ID,''spelling'' + CAST(year AS NVARCHAR(10)) AS Col, spelling AS Val FROM YourTable
)
SELECT ID, ' + @column_list + '
FROM p
PIVOT (
    MAX(Val)
    FOR Col IN (
        ' + @column_list + '
    )
) AS pvt
ORDER BY ID'

EXEC(@sql)
0 голосов
/ 15 мая 2019

Я бы предложил использовать условное агрегирование :

DECLARE @tbl TABLE(ID INT, [year] INT, reading INT, writing INT, spelling INT);
INSERT INTO @tbl VALUES
     (33087,7,625,620,686)
    ,(33087,8,544,560,541)
    ,(33205,7,559,572,497)
    ,(33205,8,599,560,612)
    ,(33902,7,500,484,464)
    ,(33902,8,607,560,686);

- запрос:

SELECT t.ID
      ,MAX(CASE WHEN t.[year]=7 THEN t.[year] END) AS year_1
      ,MAX(CASE WHEN t.[year]=7 THEN t.reading END) AS reading_1
      ,MAX(CASE WHEN t.[year]=7 THEN t.writing END) AS writing_1
      ,MAX(CASE WHEN t.[year]=7 THEN t.spelling END) AS spelling_1

      ,MAX(CASE WHEN t.[year]=8 THEN t.[year] END) AS year_2
      ,MAX(CASE WHEN t.[year]=8 THEN t.reading END) AS reading_2
      ,MAX(CASE WHEN t.[year]=8 THEN t.writing END) AS writing_2
      ,MAX(CASE WHEN t.[year]=8 THEN t.spelling END) AS spellingg_

      --add more blocks if needed
FROM @tbl t
GROUP BY t.ID;

PIVOT ограничен одним столбцом,В вашем случае вы хотите «повернуть» несколько столбцов одновременно.Этот подход обеспечивает максимальный контроль над тем, как вы вычисляете / агрегируете свои данные, если на ID и год приходится более одной строки.
Еще одно преимущество: это довольно просто создать динамически.В этом случае вам придется просматривать свои данные, находить текущие годы и создавать один блок в год.Затем вы выполняете оператор.

Другим подходом было условное объединение :

WITH IDsOnly AS
(
SELECT t.ID
FROM @tbl t
GROUP BY t.ID
)
SELECT IDsOnly.ID
      ,A.[year] AS year_1,A.reading AS reading_1,A.writing AS writing_1,A.spelling AS spelling_1
      ,B.[year] AS year_2,B.reading AS reading_2,B.writing AS writing_2,B.spelling AS spelling_2
FROM IDsOnly
LEFT JOIN(SELECT * FROM @tbl t7 WHERE t7.[year]=7) AS A ON IDsOnly.ID=A.ID
LEFT JOIN(SELECT * FROM @tbl t7 WHERE t7.[year]=8) AS B ON IDsOnly.ID=B.ID;
--Add more joins if needed...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...