为什么我在Pivot中得到4行?

时间:2019-06-06 11:44:45

标签: sql sql-server tsql pivot

数据透视

数据透视是一种对数据进行分组和聚合的技术,可将数据从行状态转换为列状态。在所有数据透视查询中,您需要确定三个元素:

  • 您想在行上看到什么?此元素称为on行或分组元素
  • 您想在列上看到什么?此元素称为on cols或 spreading元素
  • 您想在每个不同的行和列值的交集处看到什么?该元素称为数据或聚合元素

模式:

WITH PivotData AS
(
  SELECT
    < grouping column >,
    < spreading column >,
    < aggregation column >
  FROM < source table >
)
SELECT < select list >
FROM PivotData
  PIVOT( < aggregate function >(< aggregation column >)
    FOR < spreading column > IN (< distinct spreading values >) ) AS P;

我在SQL Server中创建了此表

CREATE TABLE [dbo].[NameValueData](
    [Name] [VARCHAR](50) NOT NULL,
    [Value] [INT] NOT NULL
) ON [PRIMARY]

它具有值

INSERT INTO NameValueData
VALUES
( 'N1', 1 ), 
( 'N2', 2 ), 
( 'N3', 3 ), 
( 'N4', 4 ),
--NOT FIXED Number of ROWS

数据是:

Name    Value
N1  1
N2  2
N3  3
N4  4
... ...

现在,我需要旋转该数据并获得结果,其中基于列名中的行值创建的列名

N1  N2  N3  N4  ...
1   2   3   4   --Can be more

我试图编写自己的数据透视SQL

WITH PivotData
AS (SELECT Value AS GroupingColumn,
           Name AS SpreadingColumn,
           Value AS AggregationColumn
    FROM dbo.NameValueData)
SELECT 1 AS Ignore,
       [N1],
       [N2],
       [N3],
       [N4]
FROM PivotData
    PIVOT
    (
        MAX(AggregationColumn)
        FOR SpreadingColumn IN ([N1], [N2], [N3], [N4])
    ) AS P;

结果是:

Ignore  N1  N2  N3  N4
1   1   NULL    NULL    NULL
1   NULL    2   NULL    NULL
1   NULL    NULL    3   NULL
1   NULL    NULL    NULL    4

为什么我在这里得到4行?

3 个答案:

答案 0 :(得分:2)

如果您将选择列表中的1 AS Ignore替换为GroupingColumn,将会看到为什么得到4条记录而不是一条记录的原因。

执行聚合时,PIVOT操作使用所有分组列,无论是否包含在最终投影中,都包含在隐式group by子句中。

GroupingColumn CTE和最终预测中删除PivotData将解决您的问题。

实际上,由于数据的性质,您可以完全摆脱CTE,只需使用以下查询即可:

select * 
  from namevaluedata
 pivot (max(value)
        for name in ([N1], [N2], [N3], [N4])
       ) p;

答案 1 :(得分:1)

尝试一下:

WITH PivotData
AS (SELECT Name AS SpreadingColumn,
           Value AS AggregationColumn
    FROM dbo.NameValueData)
SELECT 1 AS Ignore,
       [N1],
       [N2],
       [N3],
       [N4]
FROM PivotData
    PIVOT
    (
        MAX(AggregationColumn)
        FOR SpreadingColumn IN ([N1], [N2], [N3], [N4])
    ) AS P;

答案 2 :(得分:0)

我只是不喜欢pivot,更喜欢条件聚合。这就是原因之一。

正在生成的行由源数据中PIVOT子句中所有不是 的值确定。因为您有第三列(GroupingColumn),所以它用于定义行。