Поворот строк в столбцы без агрегата
Попытка понять, как написать динамический сводный SQL-оператор. Где TEST_NAME
может иметь до 12 различных значений (таким образом, имеет 12 столбцов). Некоторые из VAL будут типами данных Int, Decimal или Varchar. Большинство примеров, которые я видел, имеют некоторые из включенного агрегата. Я ищу для прямого значения.
Source Table
╔═══════════╦══════╦═══════╗
║ TEST_NAME ║ SBNO ║ VAL ║
╠═══════════╬══════╬═══════╣
║ Test1 ║ 1 ║ 0.304 ║
║ Test1 ║ 2 ║ 0.31 ║
║ Test1 ║ 3 ║ 0.306 ║
║ Test2 ║ 1 ║ 2.3 ║
║ Test2 ║ 2 ║ 2.5 ║
║ Test2 ║ 3 ║ 2.4 ║
║ Test3 ║ 1 ║ PASS ║
║ Test3 ║ 2 ║ PASS ║
╚═══════════╩══════╩═══════╝
Desired Output
╔══════════════════════════╗
║ SBNO Test1 Test2 Test3 ║
╠══════════════════════════╣
║ 1 0.304 2.3 PASS ║
║ 2 0.31 2.5 PASS ║
║ 3 0.306 2.4 NULL ║
╚══════════════════════════╝
Ответы
Ответ 1
Функция PIVOT
требует агрегации, чтобы заставить ее работать. Похоже, что ваш столбец VAL
- это varchar
, поэтому вам придется использовать либо агрегатные функции MAX
, либо MIN
.
Если количество тестов ограничено, вы можете жестко закодировать значения:
select sbno, Test1, Test2, Test3
from
(
select test_name, sbno, val
from yourtable
) d
pivot
(
max(val)
for test_name in (Test1, Test2, Test3)
) piv;
Смотрите SQL Fiddle with Demo.
В вашем OP вы заявили, что у вас будет большее количество строк, чтобы превратиться в столбцы. Если это так, то вы можете использовать динамический SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(TEST_NAME)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT sbno,' + @cols + '
from
(
select test_name, sbno, val
from yourtable
) x
pivot
(
max(val)
for test_name in (' + @cols + ')
) p '
execute(@query)
Смотрите SQL Fiddle with Demo.
Обе версии дадут тот же результат:
| SBNO | TEST1 | TEST2 | TEST3 |
---------------------------------
| 1 | 0.304 | 2.3 | PASS |
| 2 | 0.31 | 2.5 | PASS |
| 3 | 0.306 | 2.4 | (null) |
Ответ 2
Нет никакого способа для PIVOT без агрегации.
CREATE TABLE #table1
(
TEST_NAME VARCHAR(10),
SBNO VARCHAR(10),
VAL VARCHAR(10)
);
INSERT INTO #table1 (TEST_NAME, SBNO, VAL)
VALUES ('Test1' ,'1', '0.304'),
('Test1' ,'2', '0.31'),
('Test1' ,'3', '0.306'),
('Test2' ,'1', '2.3'),
('Test2' ,'2', '2.5'),
('Test2' ,'3', '2.4'),
('Test3' ,'1', 'PASS'),
('Test3' ,'2', 'PASS')
WITH T AS
(
SELECT SBNO, VAL, TEST_NAME
FROM #table1
)
SELECT *
FROM T
PIVOT (MAX(VAL) FOR TEST_NAME IN([Test1], [Test2], [Test3])) P
Ответ 3
Обходной путь может заключаться в обеспечении того, чтобы обязательная агрегация применялась только к одной записи. Например, в Excel вывод может быть:
![SO15674373 example]()
где Row Labels содержит внизу столбца ячеек с уникальными номерами индексов.
Ответ 4
"FOR TEST_NAME IN ([Test1], [Test2], [Test3])) P"
как использовать оператор выбора, а не значения