#sql #sql-server #tsql #pivot #dynamic-pivot
#sql #sql-сервер #tsql #сводная #динамический-сводный
Вопрос:
У меня есть таблица, разработанная в формате по столбцам, как показано ниже:
------ --------- ------------- ------------
| S_ID | S_NAME | MARK_NUMBER | MARK_VALUE |
------ --------- ------------- ------------
| 1 | TEST | MARK1 | 50 |
| 1 | TEST | MARK2 | 60 |
| 1 | TEST | MARK3 | 70 |
| 2 | TEST_! | MARK1 | 40 |
| 2 | TEST_! | MARK2 | 50 |
| 2 | TEST_! | MARK3 | 40 |
------ --------- ------------- ------------
MARK_NUMBER
в столбце будет ‘N’ количество меток. Я не могу определить ее / настроить ее статически (как упоминалось в другом ответе SO). Мне нужно преобразовать эту таблицу в формат по столбцам, как показано ниже:
S_ID S_Name MARK1 MARK2 MARK3
1 TEST 50 60 70
2 TEST_! 40 50 40
Комментарии:
1. Для достижения желаемого результата необходимо использовать сводную таблицу. Поскольку количество меток может составлять N, решением может быть динамический запрос.
Ответ №1:
Попробуйте это:
CREATE TABLE #DataSource
(
[S_ID] INT
,[S_NAME] VARCHAR(12)
,[MARK_NUMBER] VARCHAR(12)
,[MARK_VALUE] INT
);
INSERT INTO #DataSource ([S_ID], [S_NAME], [MARK_NUMBER], [MARK_VALUE])
VALUES (1, 'TEST', 'MARK1', 50)
,(1, 'TEST', 'MARK2', 60)
,(1, 'TEST', 'MARK3', 70)
,(2, 'TEST_!', 'MARK1', 40)
,(2, 'TEST_!', 'MARK2', 50)
,(2, 'TEST_!', 'MARK3', 40);
DECLARE @DynammicTSQLStatement NVARCHAR(MAX)
,@DynamicPIVOTColumns NVARCHAR(MAX);
SET @DynamicPIVOTColumns = STUFF
(
(
SELECT ',[' CAST([MARK_NUMBER] AS VARCHAR(12)) ']'
FROM #DataSource
GROUP BY [MARK_NUMBER]
ORDER BY [MARK_NUMBER]
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET @DynammicTSQLStatement = N'
SELECT *
FROM #DataSource
PIVOT
(
MAX([MARK_VALUE]) FOR [MARK_NUMBER] IN (' @DynamicPIVOTColumns ')
) PVT';
EXEC sp_executesql @DynammicTSQLStatement;
DROP TABLE #DataSource;
Ответ №2:
Моим решением был бы динамический СВОД:
DROP TABLE IF EXISTS #mytemptable
CREATE TABLE #mytemptable
(
S_ID int
,S_NAME varchar(20)
,MARK_NUMBER varchar(20)
,MARK_VALUE int
)
INSERT INTO #mytemptable VALUES
(1,'TEST ','MARK1',50),
(1,'TEST ','MARK2',60),
(1,'TEST ','MARK3',70),
(2,' TEST_!','MARK1',40),
(2,' TEST_!','MARK2',50),
(2,' TEST_!','MARK3',40)
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns = N', p.' QUOTENAME(MARK_NUMBER)
FROM (SELECT DISTINCT p.MARK_NUMBER FROM #mytemptable AS p) AS x;
SET @sql = N'
SELECT *
FROM
( select S_ID, S_NAME, MARK_VALUE, MARK_NUMBER from #mytemptable
) AS j
PIVOT
(
SUM(MARK_VALUE) FOR MARK_NUMBER IN ('
STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
')
) AS p;';
PRINT @sql;
EXEC sp_executesql @sql;
DROP TABLE IF EXISTS #mytemptable