Mi objetivo es conseguir el número acumulado de usuarios registrados por fecha.
Aquí está mi sql mysql
SELECT MONTH( DATE ) AS `month`, COUNT(userid)
FROM `stats`
WHERE `userid` = 1
GROUP BY `month`
Esto me da la cantidad de usuarios por mes, pero no los acumula
resultado:
month 1 : 90
month 2 : 50 (it should be 90 + 50)
month 3 : 10 (it should be 90 + 50 + 10)
Lo intenté:
SELECT month,
SUM( CNT ) AS CUM_CNT_TILL_NOW
FROM (
SELECT MONTH( DATE ) AS `month`, COUNT(userid) AS CNT
FROM `stats`
WHERE `userid` = 1
GROUP BY `month`
);
y se obtuvo un error: # 1248 - Cada tabla derivada debe tener su propio alias
Respuestas
2 para la respuesta № 1En MySQL, hay básicamente tres formas de hacer una suma acumulativa:
- Una subconsulta correlacionada.
- La desigualdad se une a la agregación.
- Variables.
Este último es el más sencillo. Sin embargo, debido a la forma en que group by
Funciona en MySQL, a menudo necesitas una subconsulta:
SELECT yyyy, mm, cnt,
(@sum := @sum + cnt) as cume_sum
FROM (SELECT YEAR(DATE) as yyyy, MONTH( DATE ) AS mm, COUNT(userid) AS CNT
FROM stats
WHERE userid = 1
GROUP BY yyyy, mm
) ym CROSS JOIN
(SELECT @sum := 0) params
ORDER BY yyyy, mm;
Notas:
- Esto sabiamente tiene en cuenta el año. Eso es usualmente destinado cuando estás acumulando por mes.
- los
@sum
La variable se define en la consulta. Esto es una conveniencia. - La subconsulta es necesaria porque a veces las variables no funcionan como se esperaba con las agregaciones.
- La subconsulta tiene un alias.
0 para la respuesta № 2
En Mysql, puedes hacer uso de la variable de sesión. como abajo:
SET @sum = 0;
SELECT MONTH( DATE ) AS `month`, @sum:=@sum+COUNT(userid) as sum
FROM `stats`
WHERE `userid` = 1
GROUP BY `month`;
O bien, tendrá que unir las dos tablas, pero eso sería ineficaz.
0 para la respuesta № 3
SELECT month,
SUM( CNT ) OVER ( ORDER BY month ROWS BETWEEN UNBOUNDED PRECEEDING
AND CURRENT ROW
) AS CUM_CNT_TILL_NOW
FROM
(
SELECT MONTH( DATE ) AS `month`, COUNT(userid) AS CNT
FROM `stats`
WHERE `userid` = 1
GROUP BY `month`
);
Otra solución :-
WITH tmp AS
(
SELECT MONTH( DATE ) AS `month`, COUNT(userid) AS CNT
FROM `stats`
WHERE `userid` = 1
GROUP BY `month`
)
SELECT o.month, o.cnt , RunningTotal = o.cnt + COALESCE(
(
SELECT SUM(cnt) AS cnt
FROM tmp i
WHERE i.month < o.month), 0
)
FROM tmp AS o
ORDER BY o.month;
0 para la respuesta № 4
prueba con algo como:
SELECT MONTH(DATE) AS `month`, COUNT(userid) , (SELECT COUNT(userid)
FROM `stats`
WHERE `userid` = 1 AND MONTH(date) <= MONTH(s.date))
FROM `stats` s
WHERE `userid` = 1
GROUP BY `month`
Gracias jpw por la corrección