Почему 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

вот результаты:

enter image description here

однако, если я создам таблицу с столбцом идентификатора, результаты будут разделены на отдельные строки:

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

разные результаты:

enter image description here

мне кажется, что столбец 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 Так он не будет использоваться для группировки данных.