【问题标题】:PIVOT in SQL returning may rows that aren't needed as NULLSQL 中的 PIVOT 返回可能不需要为 NULL 的行
【发布时间】:2017-10-13 15:21:42
【问题描述】:

如果这是重复的,请道歉,但我的场景非常具体到所提供的示例。

这个 PIVOT 逻辑有什么问题,导致它返回所有不需要的空值,而不是只返回包含所需列的 1 行。 (主演太久了。)

SELECT ENTITY_VAL, [12],[11],[10],[9],[8],[7],[6],[5],[4],[3],[2],[1]
    FROM
    (
    SELECT ROW_NUMBER() OVER(ORDER BY CONVERT(DATE, DATEADD(dd, -1, DATEADD(mm, DATEDIFF(mm, 0, D) + 1, 0)),121) DESC) ID 
    ,DATEPART(YEAR, D) YR
    ,DATEPART(MONTH, D) MNTH
    --,RIGHT('00' + CAST(DATEPART(mm, D) AS VARCHAR(02)), 2) MNTH2
    ,CONVERT(DATE, D, 101) FIRSTOFMONTH
    ,CONVERT(DATE, DATEADD(dd, -1, DATEADD(mm, DATEDIFF(mm, 0, D) + 1, 0)),121) LASTOFMONTH
    , 1111111 ENTITY_VAL
    FROM
        (
          SELECT D = DATEADD(MONTH, XM.RN, @StartDate)
          FROM 
          (
            SELECT TOP (DATEDIFF(MONTH, @StartDate, @CutoffDate)) 
              RN = ROW_NUMBER() OVER (ORDER BY AO.[object_id])
            FROM sys.all_objects AS AO
            CROSS JOIN sys.all_objects AS AO2
            -- on my system this would support > 5 million days
            ORDER BY AO.[object_id]
          ) AS XM
        ) AS XY
    --ORDER BY LASTOFMONTH ASC
    ) AS BASE
    PIVOT
    (
        MAX(FIRSTOFMONTH) FOR ID IN ([12],[11],[10],[9],[8],[7],[6],[5],[4],[3],[2],[1])
    ) AS PVT

我明白了(不是我想要的):

ENTITY_VAL  12         11         10         9          8          7          6          5          4          3          2          1
----------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1111111     2016-11-01 NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       2016-12-01 NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       2017-01-01 NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       2017-02-01 NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       2017-03-01 NULL       NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       2017-04-01 NULL       NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       2017-05-01 NULL       NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       NULL       2017-06-01 NULL       NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       2017-07-01 NULL       NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       2017-08-01 NULL       NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       2017-09-01 NULL
1111111     NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       NULL       2017-10-01

而不是这个(我想要的):

ENTITY_VAL  12         11         10         9          8          7          6          5          4          3          2          1
----------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1111111     2016-11-01 2016-12-01 2017-01-01 2017-02-01 2017-03-01 2017-04-01 2017-05-01 2017-06-01 2017-07-01 2017-08-01 2017-09-01 2017-10-01

【问题讨论】:

  • 我不会调试代码。但是枢轴是直截了当的。您拥有一种格式的数据并转换为数据透视格式。因此,我建议您调试子查询以确保数据格式正确。还可以简化您的代码并测试分开的每个小部分。检查manual
  • 你看到这个例子了吗?将 BASE 重写为 CTE 并执行 SELECT * FROM BASE
  • 洞察您的 cmets,别名无关紧要,我也不想要 *,因为它似乎不会消除它试图显示的多余内容。不过,我非常感谢您给我“小部分分离”这个想法的火花。
  • 我没有暗示别名问题,我的意思是分开部分以便您可以更轻松地调试它。很高兴你能解决它:)
  • 明白,为了更好的阅读方式,我倾向于大量更改别名/单词。

标签: sql-server sql-server-2012 pivot


【解决方案1】:

我修好了,是过多的列“膨胀”了 PIVOT。

更新逻辑:

SELECT ENTITY_VAL, [12],[11],[10],[9],[8],[7],[6],[5],[4],[3],[2],[1]
    FROM
    (
    SELECT ROW_NUMBER() OVER(ORDER BY CONVERT(DATE, DATEADD(dd, -1, DATEADD(mm, DATEDIFF(mm, 0, D) + 1, 0)),121) DESC) ID         
    ,CONVERT(DATE, D, 101) FIRSTOFMONTH
    ,1111111 ENTITY_VAL
    FROM
        (
          SELECT D = DATEADD(MONTH, XM.RN, @StartDate)
          FROM 
          (
            SELECT TOP (DATEDIFF(MONTH, @StartDate, @CutoffDate)) 
              RN = ROW_NUMBER() OVER (ORDER BY AO.[object_id])
            FROM sys.all_objects AS AO
            CROSS JOIN sys.all_objects AS AO2
            -- on my system this would support > 5 million days
            ORDER BY AO.[object_id]
          ) AS XM
        ) AS XY
    --ORDER BY LASTOFMONTH ASC
    ) AS BASE
    PIVOT
    (
        MAX(FIRSTOFMONTH) FOR ID IN ([12],[11],[10],[9],[8],[7],[6],[5],[4],[3],[2],[1])
    ) AS PVT

返回:

ENTITY_VAL  12         11         10         9          8          7          6          5          4          3          2          1
----------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1111111     2016-11-01 2016-12-01 2017-01-01 2017-02-01 2017-03-01 2017-04-01 2017-05-01 2017-06-01 2017-07-01 2017-08-01 2017-09-01 2017-10-01

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多