#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 )