Hay un enfoque eso puede hacer esto en SQL puro pero tiene limitaciones.
Primero debe tener una secuencia de números 1,2,3 ... n como filas (suponga que select row from rows
lo devuelve).
Luego puede unirse a esto y convertir a fechas en función del número de días entre min y max.
select @min_join_on := (select min(join_on) from user);
select @no_rows := (select datediff(max(join_on), @min_join_on) from user)+1;
le dará el número requerido de filas, que luego se puede utilizar para
select adddate(@min_join_on, interval row day) from rows where row <= @no_rows;
devolverá una secuencia necesaria de fechas en las que a continuación, puede hacer una combinación izquierda de nuevo a la tabla de usuarios .
Se pueden evitar el uso de variables si utiliza subconsultas, lo descompuse para facilitar la lectura.
Ahora, el problema es que el número de filas en la tabla rows
tiene que ser mayor que @no_rows. Para 10.000 filas puede trabajar con rangos de fechas de hasta 27 años, con 100.000 filas puede trabajar con rangos de fechas de hasta 273 años (esto se siente realmente mal, pero me temo que si no desea utilizar almacenado procedimientos que tendrá que verse y sentirse incómodo).
lo tanto, si se puede trabajar con una fecha fija rangos incluso se puede sustituir la mesa con la consulta, como este
SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4, (SELECT @row:=0) r
que producirá 10.000 filas que van de 1 a 10.000 y que no habrá terriblemente ineficiente en eso.
Por lo tanto, al final es factible en una sola consulta.
create table user(id INT NOT NULL AUTO_INCREMENT, name varchar(100), join_on date, PRIMARY KEY(id));
mysql> select * from user;
+----+-------+------------+
| id | name | join_on |
+----+-------+------------+
| 1 | user1 | 2010-04-02 |
| 2 | user2 | 2010-04-04 |
| 3 | user3 | 2010-04-08 |
| 4 | user4 | 2010-04-08 |
+----+-------+------------+
4 rows in set (0.00 sec)
insert into user values (null, 'user1', '2010-04-02'), (null, 'user2', '2010-04-04'), (null, 'user3', '2010-04-08'), (null, 'user4', '2010-04-08')
SELECT date, count(id)
FROM (
SELECT adddate((select min(join_on) from user), row-1) as date
FROM (
SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (SELECT @row:=0) r) n
WHERE n.row <= (select datediff(max(join_on), min(join_on)) from user) + 1
) dr LEFT JOIN user u ON dr.date = u.join_on
GROUP BY dr.date
+------------+-----------+
| date | count(id) |
+------------+-----------+
| 2010-04-02 | 1 |
| 2010-04-03 | 0 |
| 2010-04-04 | 1 |
| 2010-04-05 | 0 |
| 2010-04-06 | 0 |
| 2010-04-07 | 0 |
| 2010-04-08 | 2 |
+------------+-----------+
7 rows in set (0.00 sec)
+1 lo he hecho en código (fuera de SQL), pero muy interesante ver si algunas soluciones limpias SQL de sólo aparecerá – Tomas
Este es un comúnmente preguntado y respondido a la pregunta sobre el SO (búsqueda de 'date 'y' [sql] 'o' [mysql] '). Véase, por ejemplo, http://stackoverflow.com/questions/1046865/mysql-select-all-dates-in-a-range-even-if-no-records-present – pilcrow
@pilcrow: es una pregunta frecuente, pero la respuesta vinculada no es particularmente exhaustiva en los detalles. @OP: normalmente este tipo de cosas no es tan fácil en las bases de datos que no admiten SQL recursivo; todavía publiqué algunos SQL (con algunos problemas, pero podría ser útil) – Unreason