Почему pivot с" дополнительными " столбцами не объединяет результаты
Я знаю, что многие из вас наблюдали такое поведение, но мне интересно, может ли кто-нибудь объяснить, почему. Когда я создаю небольшую таблицу для создания примера использования функции pivot, я получаю ожидаемые результаты:
CREATE TABLE dbo.AverageFishLength
(
Fishtype VARCHAR(50) ,
AvgLength DECIMAL(8, 2) ,
FishAge_Years INT
)
INSERT INTO dbo.AverageFishLength
( Fishtype, AvgLength, FishAge_Years )
VALUES ( 'Muskie', 32.75, 3 ),
( 'Muskie', 37.5, 4 ),
( 'Muskie', 39.75, 5 ),
( 'Walleye', 16.5, 3 ),
( 'Walleye', 18.25, 4 ),
( 'Walleye', 20.0, 5 ),
( 'Northern Pike', 20.75, 3 ),
( 'Northern Pike', 23.25, 4 ),
( 'Northern Pike', 26.0, 5 );
вот сводный запрос:
SELECT Fishtype ,
[3] AS [3 Years Old] ,
[4] AS [4 Years Old] ,
[5] AS [5 Years Old]
FROM dbo.AverageFishLength PIVOT( SUM(AvgLength)
FOR FishAge_Years IN ( [3], [4], [5] ) ) AS PivotTbl
вот результаты:
однако, если я создам таблицу с столбцом идентификатора, результаты будут разделены на отдельные строки:
DROP TABLE dbo.AverageFishLength
CREATE TABLE dbo.AverageFishLength
(
ID INT IDENTITY(1,1) ,
Fishtype VARCHAR(50) ,
AvgLength DECIMAL(8, 2) ,
FishAge_Years INT
)
INSERT INTO dbo.AverageFishLength
( Fishtype, AvgLength, FishAge_Years )
VALUES ( 'Muskie', 32.75, 3 ),
( 'Muskie', 37.5, 4 ),
( 'Muskie', 39.75, 5 ),
( 'Walleye', 16.5, 3 ),
( 'Walleye', 18.25, 4 ),
( 'Walleye', 20.0, 5 ),
( 'Northern Pike', 20.75, 3 ),
( 'Northern Pike', 23.25, 4 ),
( 'Northern Pike', 26.0, 5 );
же точный запрос:
SELECT Fishtype ,
[3] AS [3 Years Old] ,
[4] AS [4 Years Old] ,
[5] AS [5 Years Old]
FROM dbo.AverageFishLength PIVOT( SUM(AvgLength)
FOR FishAge_Years IN ( [3], [4], [5] ) ) AS PivotTbl
разные результаты:
мне кажется, что столбец ID используется в запросе, хотя он вообще не отображается в запросе. Это почти так же, как он неявно включен в запрос, но не показан в результирующем наборе.
может кто-нибудь объяснить, почему это происходит?
1 ответов
это происходит потому, что ID
столбец уникален для каждой строки, и поскольку вы запрашиваете таблицу напрямую (без подзапроса), этот столбец включен как часть GROUP BY
требуется агрегатная функция.
документы на документы MSDN о FROM
следующее:
table_source PIVOT <pivot_clause>
указывает, что table_source поворачивается на основе pivot_column. table_source-это таблица или табличное выражение. Этот выходные данные-это таблица, содержащая все столбцы table_source, кроме pivot_column и value_column. The столбцы table_source, за исключением pivot_column и value_column, называют группировка столбцов оператора pivot.
PIVOT
выполняет операцию группировки на входной таблице что касается группирования столбцов и возвращает одна строка для каждой группы. Дополнительно, выход содержит одно столбец для каждого значения, указанного в column_list, который отображается в pivot_column input_table.
ваша версия в основном говорят SELECT * FROM yourtable
и свернуть эти данные. Хотя ID
столбец не входит в окончательный список выбора, это элемент группировки в запросе. Если вы сравните PIVOT с примером "pre-PIVOT", чтобы показать, что вы увидите, что ваша версия. В этом примере используется выражение CASE и агрегатная функция:
SELECT Fishtype,
sum(case when FishAge_Years = 3 then AvgLength else 0 end) as [3],
sum(case when FishAge_Years = 4 then AvgLength else 0 end) as [4],
sum(case when FishAge_Years = 5 then AvgLength else 0 end) as [5]
FROM dbo.AverageFishLength
GROUP BY Fishtype, ID;
результат будет перекос, потому что, хотя у вас нет ID
в конечном списке он все еще используется для группировки и, поскольку они уникальны, вы получаете несколько строк.
самый простой способ решить эту проблему при использовании PIVOT - использовать подзапрос:
SELECT Fishtype ,
[3] AS [3 Years Old] ,
[4] AS [4 Years Old] ,
[5] AS [5 Years Old]
FROM
(
SELECT Fishtype,
AvgLength,
FishAge_Years
FROM dbo.AverageFishLength
) d
PIVOT
(
SUM(AvgLength)
FOR FishAge_Years IN ( [3], [4], [5] )
) AS PivotTbl;
в этой версии вы возвращаете только столбцы, которые вам действительно нужны и нужны из вашей таблицы-это исключает ID
Так он не будет использоваться для группировки данных.