将累积(运行)总计添加到TSQL查询(SQL Server 2008)?

时间:2014-05-24 02:05:33

标签: sql-server-2008 tsql aggregation

我有以下查询,显示特定日期范围的每周总计:

declare @from_date datetime
declare @to_date datetime

SET @from_date = '2014-03-30';    
SET @to_date = '2014-08-10';    

SELECT DATEDIFF(week, 0, IDOC.Import_Date) Week,
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) 'From Date',
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) + 6 'End Date',
    COUNT(IDOC.IDOC_ID) 'Total'
FROM IDOC    
INNER JOIN dbo.File_Type FI     
        on IDOC.File_Type_ID = FI.File_Type_ID    
INNER JOIN  IDOC_Team_Assignment ITA    
    ON IDOC.IDOC_ID=ITA.IDOC_ID    
Where IDOC.Import_Date BETWEEN @from_date AND @to_date
GROUP BY DATEDIFF(week, 0, IDOC.Import_Date) 
ORDER BY DATEDIFF(week, 0, IDOC.Import_Date)

输出:

Week    | From Date      | End Date      | Total
--------------------------------------------------
5965    2014-04-28    2014-05-04        1
5967    2014-05-12    2014-05-18      1
5968    2014-05-19    2014-05-25      2

我想添加累计总数(运行总计)这是我想要完成的事情

 Week    | From Date      | End Date      | Total | Cummulative
    -------------------------------------------------------------
    5965    2014-04-28    2014-05-04        1       1
    5967    2014-05-12    2014-05-18      1         2
    5968    2014-05-19    2014-05-25      2         4

1 个答案:

答案 0 :(得分:1)

xQbert给你的链接向你展示了这个概念,但当你的选择中已经有另一个 count 时,它可能会有点混乱。

您需要删除组,并在计数上使用 over ,限制一个只计算 分组你已经拥有,第二个覆盖整个范围。

在这种情况下,您不能使用行前未绑定,因为它将为每一行创建一个条目,而不是在现有结果集上构建。但您确实需要在 over 选择结束时保持顺序

您还需要添加 distinct 关键字。

SELECT DISTINCT
    DATEDIFF(week, 0, IDOC.Import_Date) Week,
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) 'From Date',
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) + 6 'End Date',
    COUNT(IDOC.IDOC_ID) OVER (PARTITION BY DATEDIFF(week, 0, IDOC.Import_Date)) 'Total',
    COUNT(IDOC.IDOC_ID) OVER (ORDER BY DATEDIFF(week, 0, IDOC.Import_Date)) 'Running Total'
FROM IDOC    
INNER JOIN dbo.File_Type FI     
        on IDOC.File_Type_ID = FI.File_Type_ID    
INNER JOIN  IDOC_Team_Assignment ITA    
    ON IDOC.IDOC_ID=ITA.IDOC_ID    
WHERE IDOC.Import_Date BETWEEN @from_date AND @to_date
ORDER BY DATEDIFF(week, 0, IDOC.Import_Date)

我无法在SQL Server 2008上对此进行测试,但我确实在VS2013免费试用了它,我知道它可以在Oracle中运行。值得一试。

这个在SQL Server 2008 R2上测试过 - 我希望你不急于获得这些数据......

SELECT
    DATEDIFF(week, 0, IDOC.Import_Date) Week,
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) 'From Date',
    DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) + 6 'End Date',
    COUNT(IDOC.IDOC_ID) 'Total',
    (
        SELECT
            COUNT(aIDOC.IDOC_ID)
        FROM
            IDOC aIDOC
        INNER JOIN dbo.File_Type aFI     
            ON aIDOC.File_Type_ID = aFI.File_Type_ID    
        INNER JOIN IDOC_Team_Assignment aITA    
            ON aIDOC.IDOC_ID=aITA.IDOC_ID    
        WHERE
            aIDOC.Import_Date BETWEEN @from_date AND @to_date
            AND DATEDIFF(week, 0, IDOC.Import_Date) <= DATEDIFF(week, 0, aIDOC.Import_Date)
    ) 'RunningTotal'
FROM
    IDOC
INNER JOIN dbo.File_Type FI     
    ON IDOC.File_Type_ID = FI.File_Type_ID    
INNER JOIN  IDOC_Team_Assignment ITA    
    ON IDOC.IDOC_ID=ITA.IDOC_ID    
WHERE
    IDOC.Import_Date BETWEEN @from_date AND @to_date
GROUP BY
    DATEDIFF(week, 0, IDOC.Import_Date) 
ORDER BY
    DATEDIFF(week, 0, IDOC.Import_Date)

现在我把它变成了一个看起来更干净的CTE。

WITH CTE( WeekNbr, FromDate, EndDate, Total) AS (
    SELECT
        DATEDIFF(week, 0, IDOC.Import_Date) 'WeekNbr',
        DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) 'FromDate',
        DATEADD(week, DATEDIFF(week, 0, IDOC.Import_Date), 0) + 6 'EndDate',
        COUNT(IDOC.IDOC_ID) 'Total'
    FROM
        IDOC
    INNER JOIN dbo.File_Type FI     
        ON IDOC.File_Type_ID = FI.File_Type_ID    
    INNER JOIN  IDOC_Team_Assignment ITA    
        ON IDOC.IDOC_ID=ITA.IDOC_ID    
    WHERE
        IDOC.Import_Date BETWEEN @from_date AND @to_date
    GROUP BY
        DATEDIFF(week, 0, IDOC.Import_Date) 
)
SELECT
    A.WeekNbr,
    A.FromDate,
    A.EndDate,
    A.Total,
    (SELECT SUM(B.Total) FROM CTE B WHERE B.WeekNbr <= A.WeekNbr) 'RunningTotal'
FROM
    CTE A
ORDER BY
    A.WeekNbr