Error al calcular un total acumulado (acumulado en los períodos anteriores)

Tengo una tabla, llamémosla My_Table que tiene una columna de date Created hora Created (en SQL Server) que estoy tratando de extraer un informe que muestra históricamente cuántas filas fueron a My_Table por mes durante un time en particular. Ahora sé que puedo mostrar cuántos se agregaron cada mes con:

 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) 

Que devolvería algo así como:

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

Sin embargo, quiero get el tamaño total de la list durante el período determinado (llámalo como quieras; un total acumulado, una sum acumulativa, un informe histórico):

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

Estoy intentando esto:

 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) 

Sin embargo, SQL Server está respondiendo con este error:

 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. 

Solo sé que me estoy perdiendo algo obvio, pero después de irme y regresar y mirarlo por un rato, estoy perdido. Entonces, si alguien tuviera la amabilidad de señalar qué demonios me falta aquí (o señalarme una mejor forma de hacerlo), estaría eternamente agradecido.

"Correr" implica fila por fila. Entonces, una forma es sumr meses anteriores y agregarlo al mes actual. Para lidiar con los límites del año, también toma la date mínima / máxima por grupo. El CROSS APPLY es ligeramente RBAR pero deja en claro (¿eh?) Lo que está sucediendo.

 ;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 

¿Estás en 2005 o después? Puedes romper esto usando un 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 

Podría sacar el agregado de la consulta final con algo como esto:

 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] 

Creo que debería cubrir todos los pedidos anteriores en un año anterior o en un mes anterior en el mismo año junto con todos los pedidos de ese mes.

Llámalo de manera lenta, pero podrías hacerlo con una function. No lo hagas si My_Table es grande.

 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