SQL Server中的PIVOT没有聚合函数

时间:2014-04-29 08:43:27

标签: sql-server pivot

我有一个这样的表(让我们称之为T1):

   Date    | Category | Data
-------------------------------
2014-01-01 | 1        | 1.0
2014-01-01 | 2        | 2.0
2014-01-01 | 3        | 3.0
2014-01-02 | 1        | 4.0
2014-01-02 | 2        | 5.0
2014-01-02 | 3        | 6.0

请注意Data是浮点数,而不是顺序,我只是这样做,所以更容易看到它们在结果中的位置。还有一个表格将Category数字翻译成名称(假设(T2):

Category | Name
----------------
1        | A
2        | B
3        | C

我想要一个可以返回的查询:

   Date    |   B   |   C   
---------------------------
2014-01-01 |  2.0  |  3.0  
2014-01-02 |  5.0  |  6.0

我考虑尝试使用之前没有使用过的PIVOT,但是,如果不使用聚合功能,我找不到办法。但后来我认为,因为我实际上每个Date / Category组合只有一行使用类似AVG的聚合应该有效。这是我基于these docs的尝试:

SELECT [Date],
       [2] as B,
       [3] as C
FROM (SELECT * FROM T1 WHERE Category >= 2) AS SourceTable
PIVOT
(
    AVG(Data)
    FOR Category IN ([2], [3])
) AS PivotTable;

有点接近:

   Date    |   B   |   C   
---------------------------
2014-01-01 |  2.0  |  NULL  
2014-01-01 |  NULL |  3.0
2014-01-02 |  5.0  |  NULL
2014-01-02 |  NULL |  6.0

但是我如何摆脱空值并将所有相同的日期放在同一行?

1 个答案:

答案 0 :(得分:1)

如果每个结果只有一个值,则可以使用任何聚合函数 - 例如:MAX

select * from 
    (select t.date, t.data,c.name from t1 t inner join category c on t.category = c.category) s
pivot (max(data) for name in ([b],[c])) p

第一部分是源数据

select t.date, t.data,c.name from t1 t inner join category c on t.category = c.category

然后pivot重新排列它,为in列中的name值创建列,并使用聚合(max(data))作为该列中的值,这应该会产生预期的效果。

如果您获得空值,可能是在源查询中使用select *,而不是选择必填字段 - 即:replace

SELECT * FROM T1 WHERE Category >= 2

select category, data FROM T1 WHERE Category >= 2