PIVOT 不在 DENSE_RANK 列上工作

PIVOT Not Working on a DENSE_RANK Column

我正在编写一份报告,其中提供了每日运营数据的每周总计。报告顶部将有 8 周作为列。每一排都是一辆车。诸如日期范围之类的变量最终将变成动态的,在我开发它的时候,这现在有点硬编码。 8 周可以保持硬编码。

这非常有效:

SELECT vehicle, [2] AS W2, [3] AS W3, [4] AS W4, [5] AS W5, [6] AS W6, [7] AS W7, [8] AS W8, [9] AS W9
FROM
(
    SELECT 
        Vehicle
        ,datepart(week,recordedoneffective) as WeekNum
        ,sum(totalweight ) AS TotalWeight
    from vw_visit_details v, vw_food_stats f
    where v.VisitId = f.VisitId
    and recordedoneffective between '2015-01-05' and '2015-03-01'
    group by vehicle,datepart(week,recordedoneffective)
) src
PIVOT
(
    SUM(TotalWeight) 
    FOR WeekNum IN ([2],[3],[4],[5],[6],[7],[8],[9])
    ) pvt
ORDER BY pvt.vehicle

结果:

Vehicle             W2      W3      W4      W5      W6      W7      W8      W9
Apples - D44CW      2603    7840    3200    1540    3516    2828    3217    3911
Bananas - 664SEC    4063    5004    5935    8734    8333    8663    4591    7807
Capsicum - YPD094   4699    6191    6423    4560    5742    7004    7204    5347

但是,由于 WeekNum 会根据指定的日期而变化,我想将 WeekNum 转换为一个排名,该排名将始终保持不变。为此,我使用了 DENSE_RANK,因此将 8 周数字(在本例中为 2-9)的范围转换为数字 1-8。

SELECT vehicle, [1] AS W1, [2] AS W2, [3] AS W3, [4] AS W4, [5] AS W5, [6] AS W6, [7] AS W7, [8] AS W8
FROM
(
        select 
        Vehicle
        ,datepart(week,recordedoneffective) as WeekNum
        ,dense_rank() OVER ( ORDER BY datepart    (week,recordedoneffective) ) AS WeekSeq
        ,sum(totalweight ) AS TotalWeight
    from vw_visit_details v, vw_food_stats f
    where v.VisitId = f.VisitId
    and recordedoneffective between '2015-01-05' and '2015-03-01'
    group by vehicle,   datepart(week,recordedoneffective)
) src
PIVOT
(
    SUM(TotalWeight) 
    FOR WeekSeq IN ([1],[2],[3],[4],[5],[6],[7],[8])
    ) pvt
ORDER BY pvt.vehicle

请注意,列名现在是 1-8 而不是 2-9,并且数据透视列已更改。但是现在其余的集没有正确旋转。

Vehicle         W1      W2      W3      W4      W5      W6      W7      W8
Apples - D44CW  2603    NULL    NULL    NULL    NULL    NULL    NULL    NULL
Apples - D44CW  NULL    7840    NULL    NULL    NULL    NULL    NULL    NULL
Apples - D44CW  NULL    NULL    3200    NULL    NULL    NULL    NULL    NULL
Apples - D44CW  NULL    NULL    NULL    1540    NULL    NULL    NULL    NULL
Apples - D44CW  NULL    NULL    NULL    NULL    3516    NULL    NULL    NULL
Apples - D44CW  NULL    NULL    NULL    NULL    NULL    2828    NULL    NULL
Apples - D44CW  NULL    NULL    NULL    NULL    NULL    NULL    3217    NULL
Apples - D44CW  NULL    NULL    NULL    NULL    NULL    NULL    NULL    3911
Bananas - 664SEC    4063    NULL    NULL    NULL    NULL    NULL    NULL    NULL

所以基本上,枢轴不再旋转了。两个查询的内部 src 结果集完全相同(除了添加新列)- 返回相同数量的结果,没有新的空值等。

我想也许我需要 GROUP BY dense_rank() OVER ( ORDER BY datepart(week,recordedoneffective) ) 列,但您不能按此分组。还认为我应该尝试删除现在未使用的 datepart(week,recordedoneffective) 计算列 - 事实证明,为了在 OVER 子句中使用它,仍然必须将它放在那里。

为什么这个枢轴不起作用?大概我可以用更动态的方式解决这个问题 SQL,但我看不出为什么这不起作用。

您想 GROUP BY 在执行 DENSE_RANK() 之前的一个步骤中,因为您没有在 PIVOT 输出中使用 WeekNum

;WITH cte AS (SELECT Vehicle
                    ,datepart(week,recordedoneffective) as WeekNum                  
                    ,sum(totalweight ) AS TotalWeight
              FROM vw_visit_details v, vw_food_stats f
              WHERE v.VisitId = f.VisitId
                and recordedoneffective between '2015-01-05' and '2015-03-01'
              GROUP BY vehicle,   datepart(week,recordedoneffective)
              )
     ,cte2 AS (SELECT  vehicle 
                      ,dense_rank() OVER ( ORDER BY WeekNum ) AS WeekSeq 
                      ,TotalWeight
               FROM cte
               )
SELECT vehicle, [1] AS W1, [2] AS W2, [3] AS W3, [4] AS W4, [5] AS W5, [6] AS W6, [7] AS W7, [8] AS W8
FROM cte2
PIVOT (SUM(TotalWeight) FOR WeekSeq IN ([1],[2],[3],[4],[5],[6],[7],[8])) pvt
ORDER BY pvt.vehicle

您的 CTE 有四列:Vehicle、WeekNum、WeekSeq 和 TotalWeight。 PIVOT 子句引用了最后两个;这意味着枢轴的隐式分组基于前两列。因此,对于 Vehicle 和 WeekNum 的每个唯一组合,您都会得到一行。这在您的结果集中并不清楚,因为您没有选择 WeekNum。

对于您的情况,答案很简单 - 从 CTE 中删除 WeekNum,因为您实际上并没有使用它。