SQL Server n раз исправил сводку

#sql-server #pivot #rows #common-table-expression

#sql-сервер #pivot #строки #common-table-expression

Вопрос:

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

Другими словами, что у меня есть:
введите описание изображения здесь

И что мне нужно:

введите описание изображения здесь

Я не знаю, должен ли я подойти к этому с помощью pivot или CTE и цикла … вы можете мне помочь?

Использование SQL Server 2008.

Ответ №1:

Вы можете использовать ROW_NUMBER и условное агрегирование для выполнения этого поворота

 WITH cte
     AS (SELECT RECORD_ID,
                NUMBER,
                Row_number() OVER(PARTITION BY RECORD_ID ORDER BY NUMBER ) AS RN
         FROM   yourtable)
SELECT RECORD_ID,
       COALESCE(Max(CASE WHEN rn = 1 THEN NUMBER END),0) AS NUMBER01,
       COALESCE(Max(CASE WHEN rn = 2 THEN NUMBER END),0) AS NUMBER02,
       COALESCE(Max(CASE WHEN rn = 3 THEN NUMBER END),0) AS NUMBER03,
       COALESCE(Max(CASE WHEN rn = 4 THEN NUMBER END),0) AS NUMBER04,
       COALESCE(Max(CASE WHEN rn = 5 THEN NUMBER END),0) AS NUMBER05,
       ...
       COALESCE(Max(CASE WHEN rn = 10 THEN NUMBER END),0) AS NUMBER10
FROM   CTE
GROUP  BY RECORD_ID 
 

Динамический подход

 DECLARE @x        INT = 10, -- Replace it with required of columns 
        @intr     INT = 1,
        @col_list VARCHAR(8000)='',
        @sql      VARCHAR(max)=''

SET @sql = '    WITH cte
         AS (SELECT RECORD_ID,
                    NUMBER,
                    Row_number() OVER(PARTITION BY RECORD_ID ORDER BY NUMBER ) AS RN
             FROM   yourtable)
    SELECT RECORD_ID, '


/*nothing to worry about the below while loop it is just to frame the string*/
WHILE @intr <= @x
  BEGIN
      SET @col_list  = 'COALESCE(Max(CASE WHEN rn = '   Cast(@intr AS VARCHAR(50))   ' THEN NUMBER END),0) AS NUMBER'   Cast(@intr AS VARCHAR(50))   ','
      SET @intr  = 1
  END

SET @col_list = LEFT(@col_list, Len(@col_list) - 1)
SET @sql  = @col_list   ' FROM   CTE
    GROUP  BY RECORD_ID '

EXEC ( @sql )