计算运行总计时出错(以前期间累计)

时间:2010-11-05 15:40:15

标签: sql tsql subquery aggregate

我有一个表,我们称之为My_Table日期时间为Created的日期时间列(在SQL Server中),我正在尝试提取一个报告,该报告显示历史记录中有多少行{{ 1}}按月在特定时间内完成。现在我知道我可以通过以下方式显示每月添加的数量:

My_Table

会返回类似的内容:

SELECT YEAR(MT.Created), MONTH(MT.Created), COUNT(*) AS [Total Added]
FROM My_Table MT
GROUP BY YEAR(MT.Created), MONTH(MT.Created)
ORDER BY YEAR(MT.Created), MONTH(MT.Created)

但是,我希望在给定时间段内获得列表大小(称之为“运行总计,累计金额,历史报告)”:

YEAR    MONTH     Total Added
-----------------------------
2009    01        25
2009    02        127
2009    03        241

我正在尝试这个:

   YEAR    MONTH     Total Size
   -----------------------------
-- 2008    12        325
   2009    01        350
   2009    02        477
   2009    03        718

但是,SQL Server正在响应此错误:

SELECT YEAR(MT.Created)
    , MONTH(MT.Created)
    ,(
    SELECT COUNT(*) FROM My_Table MT_int
    WHERE MT_int.Created BETWEEN 
        CAST('2009/01/01' AS datetime)
        AND DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,MT.Created)+1,0))
        -- the last day of the current month
        -- (Additional conditions can go here)
    ) AS [Total added this month]
FROM My_Table MT
WHERE MT.Created > CAST('2009/01/01' AS datetime)
GROUP BY YEAR(MT.Created), MONTH(MT.Created)
ORDER BY YEAR(MT.Created), MONTH(MT.Created)

我只是知道我错过了一些明显的东西,但走开后回来盯着它看了一会儿我不知所措。所以,如果有人能够指出我在这里错过的 earth 上的东西(或指向我更好的方式),我将永远感激。

4 个答案:

答案 0 :(得分:4)

“正在运行”意味着逐行。因此,一种方法是将前几个月相加并将其添加到当前月份。为了处理年份边界,您还可以获取每组的最小/最大日期。 CROSS APPLY略有RBAR,但很明显(呃?)发生了什么。

;WITH cTE AS
(
SELECT
     MIN(Created) AS FirstPerGroup,
     MAX(Created) AS LastPerGroup,
     YEAR(MT.Created) AS yr, MONTH(MT.Created) AS mth, COUNT(*) AS [Monthly Total Added]
FROM MY_Table MT
GROUP BY YEAR(MT.Created), MONTH(MT.Created)
)
SELECT
   C1.yr, c1.mth, SUM(C1.[Monthly Total Added]),
   ISNULL(PreviousTotal, 0) + SUM(C1.[Monthly Total Added]) AS RunningTotal
FROM
 cTE c1
 CROSS APPLY
 (SELECT SUM([Monthly Total Added]) AS PreviousTotal FROM cTE c2 WHERE c2.LastPerGroup < C1.FirstPerGroup) foo
GROUP BY
  C1.yr, c1.mth, PreviousTotal
ORDER BY
   C1.yr, c1.mth

答案 1 :(得分:2)

你是在2005年还是以后,你可以使用CTE打破这个

WITH CTE AS (
SELECT YEAR(MT.Created) as Yr 
    , MONTH(MT.Created) as Mth
    ,( 
    SELECT COUNT(*) FROM My_Table MT_int 
    WHERE MT_int.Created BETWEEN  
        CAST('2009/01/01' AS datetime) 
        AND DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,MT.Created)+1,0)) 
        -- the last day of the current month 
        -- (Additional conditions can go here) 
    ) AS Total 
FROM My_Table MT 
WHERE MT.Created > CAST('2009/01/01' AS datetime))

SELECT Yr, Mth, SUM(Total) as Total FROM CTE
GROUP BY Yr, Mth 
ORDER BY Yr, Mth 

答案 2 :(得分:1)

您可以使用以下内容从最终查询中取出聚合:

WITH CTE AS 
(SELECT DISTINCT YEAR(MT.Created) AS [Year]
    , MONTH(MT.Created) AS [Month]
FROM My_Table MT
WHERE MT.Created > CAST('2009/01/01' AS datetime)
)
SELECT MT.[Year]
    , MT.[Month]
    ,(
    SELECT COUNT(*) FROM My_Table MT_int
    WHERE MT_int.Created >= CAST('2009/01/01' AS datetime)
        AND (YEAR(MT_int.Created) < MT.[Year]
            OR (YEAR(MT_int.Created) = MT.[Year]
                AND MONTH(MT_int.Created) <= MT.[Month])
            )
        -- the last day of the current month
        -- (Additional conditions can go here)
    ) AS [Total added this month]
FROM CTE MT
ORDER BY MT.[Year], MT.[Month]

我认为应该涵盖去年同一年或过去一个月的所有过去订单以及该月的所有订单。

答案 3 :(得分:0)

以慢的方式调用它,但你可以用一个函数来做。如果My_Table很大,请不要这样做。

Create Function [dbo].[RunningTotal](@Yr int, @Mnth int)
 Returns int
AS
BEGIN
 Declare @RC int
 Select @RC=count(*)
 From My_Table
 Where Year(Created)<@Yr or (Year(Created)=@Yr and Month(Created) <= @Mnth)

 Return @RC
END