PIVOT不在DENSE_RANK列上工作

时间:2015-05-01 02:32:48

标签: sql sql-server pivot

我正在撰写一份报告,其中列出了每日运营数据的每周总数。报告顶部将有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)计算的col - 事实证明,为了在OVER子句中使用它仍然是必不可少的。

为什么这个支点不起作用?据推测,我可以使用更具动态性的SQL解决问题,但我认为没有理由说这不起作用。

2 个答案:

答案 0 :(得分:2)

您的CTE有四列:Vehicle,WeekNum,WeekSeq和TotalWeight。 PIVOT子句引用了后两个;这意味着数据透视的隐式分组基于前两列。因此,对于Vehicle和WeekNum的每个唯一组合,您将获得一行。这在您的结果集中不明确,因为您没有选择WeekNum。

在您的情况下,答案很简单 - 从CTE中删除WeekNum,因为您实际上并未使用它。

答案 1 :(得分:1)

由于您未使用GROUP BY输出中的DENSE_RANK(),因此您需要在WeekNum之前执行PIVOT步骤。

;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