代码之家  ›  专栏  ›  技术社区  ›  Sean Vieira

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

  •  2
  • Sean Vieira  · 技术社区  · 14 年前

    我有一张桌子,就叫它吧 My_Table Created datetime列(在SQL Server中),我正试图拉取一个报告,该报告显示历史上有多少行要 我的桌子 补充 每月:

    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
    

    我在尝试:

    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)
    

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

    Msg 8120, Level 16, State 1, Line 1
    Column 'My_Table .Created' is invalid in the select list because 
    it is not contained in either an aggregate function or the GROUP BY clause.
    

    我只是 我漏掉了一些显而易见的东西,但在走开回来盯着它看了一会儿之后,我不知所措。如果有人能指出 我错过了这里(或者给我指一个更好的方法)我会永远感激。

    4 回复  |  直到 10 年前
        1
  •  4
  •   gbn    14 年前

    “运行”意味着逐行运行。一种方法是把前几个月加起来,加到当前月份。为了处理年份界限,您还需要为每个组设置最小/最大日期。交叉应用是轻微的RBAR,但清楚(er?)发生了什么。

    ;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
    
        2
  •  2
  •   anivas    14 年前

    你是在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 
    
        3
  •  1
  •   Bryant Bowman    14 年前

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

    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]
    

    我认为这应该包括过去一年或同年前一个月的所有订单以及该月的所有订单。

        4
  •  0
  •   Bill    14 年前

    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