关于 tsql:SQL Pivot Table On A Common Table Expression

SQL Pivot Table On A Common Table Expression

我正在尝试使用公用表表达式创建数据透视表,但我的数据透视表在数据透视列中返回 NULL 值。当我从 cte 中选择 * 时,我的结果与我预期的一样返回。我可以使用一些帮助来弄清楚为什么我的数据透视表无法正常工作。

我的公用表表达式连接两个如下所示的表:

生产线

1
2
3
4
ID | ProductionLine
--------------------
1  | Line A
2  | Line B

生产数据

1
2
3
4
5
ID | ProductionLine_ID | UnitsProduced | ProductionDate
-------------------------------------------------------
1  | 1                 | 200           | 2014-09-18
2  | 2                 | 50            | 2014-09-18
3  | 1                 | 100           | 2014-09-19

所有 ID 都是 int 字段。 UnitsProduced 是一个 int 字段。 ProductionDate 是一个日期时间字段
这是我的 sql 查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;WITH cte AS (SELECT pl.ProductionLine AS ProductionLine, pd.ProductionDate AS ProductionDate, pd.UnitsProduced AS UnitsProduced
FROM ProductionLine pl
JOIN
ProductionData pd ON pl.ID = pd.ProductionLine_ID
)

SELECT * FROM
(
    SELECT ProductionLine,
    ProductionDate,
    UnitsProduced
    FROM  cte
) x
pivot
(
    MAX(UnitsProduced)
    FOR ProductionLine IN ([Line A])
) pvt

我应该得到如下所示的结果:

1
2
3
4
ProductionDate | Line A
-----------------------
2014-09-18     | 200
2014-09-19     | 100

但是,我的结果是这样的:

1
2
3
4
ProductionDate | Line A
-----------------------
2014-09-18     | NULL
2014-09-19     | NULL

任何帮助将不胜感激

谢谢


如果数据有 NULL,那么 select 子句会做这样的事情是非常常见的:

SELECT ISNULL([FieldName],0) as [FieldName] FROM SOMTEABLE

好吧,使用 PIVOT 的查询没有什么不同,您仍然可以通过 SELECT clause 解决 NULL 问题,尽管这里的一个问题是您使用了"select *"并且此快捷方式隐藏了您可以解决的位置问题。

使用 CTE 的语法。请注意,现在详细说明了"选择 *"的内容,并且使用了 ISNULL(.....,0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
;WITH
      cte
      AS (
            SELECT
                  pl.ProductionLine AS ProductionLine
                , pd.ProductionDate AS ProductionDate
                , pd.UnitsProduced  AS UnitsProduced
            FROM ProductionLine pl
                  JOIN ProductionData pd
                              ON pl.ID = pd.ProductionLine_ID
            )

SELECT
      ISNULL([Line A], 0) [Line A]
    , ISNULL([Line B], 0) [Line B]
FROM (
      SELECT
            ProductionLine
          , ProductionDate
          , UnitsProduced
      FROM cte
      ) x
PIVOT
      (
      MAX(UnitsProduced)
      FOR ProductionLine IN ([Line A], [Line B])
      ) pvt
;

我个人不建议使用 CTE,除非有证明需要它,这在此处不正确,一个简单的子查询将使用稍微简单的语法完成完全相同的工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT
      ISNULL([Line A], 0) [Line A]
    , ISNULL([Line B], 0) [Line B]
FROM (
      SELECT
            pl.ProductionLine AS ProductionLine
          , pd.ProductionDate AS ProductionDate
          , pd.UnitsProduced  AS UnitsProduced
      FROM ProductionLine pl
            JOIN ProductionData pd
                        ON pl.ID = pd.ProductionLine_ID
      ) x
PIVOT
      (
      MAX(UnitsProduced)
      FOR ProductionLine IN ([Line A], [Line B])
      ) pvt
;

在 SQLFiddle

中查看此工作

COALESCE()ISNULL()

我在上面使用了特定于 TSQL 的 ISNULL(),PIVOT 语法也是如此。 Stackoverflow 建议尽可能使用标准 SQL,因此请注意在上面的查询中可以使用 COALESCE() 而不是 ISNULL()。但也要注意这些功能并不完全相同。