données de tout mois Il y a une approche cela peut le faire en pur SQL mais il a des limites.
Vous devez d'abord avoir une séquence de nombres 1,2,3 ... n en tant que lignes (supposons que select row from rows
renvoie cela).
Ensuite, vous pouvez vous joindre à cela et convertir en dates en fonction du nombre de jours entre min et 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;
vous donnera le nombre requis de lignes, ce qui vous pouvez utiliser pour
select adddate(@min_join_on, interval row day) from rows where row <= @no_rows;
renverra une séquence requise de dates auxquelles vous pouvez faire une gauche rejoindre à la table des utilisateurs .
L'utilisation de variables peut être évitée si vous utilisez des sous-requêtes, je l'ai décomposé pour la lisibilité.
Maintenant, le problème est que le nombre de lignes dans la table rows
doit être plus grand que @no_rows. Pour 10 000 lignes, vous pouvez travailler avec des plages de dates allant jusqu'à 27 ans, avec 100 000 lignes, vous pouvez travailler avec des plages de dates allant jusqu'à 273 ans (cela semble vraiment mauvais, mais je crains que si vous ne voulez pas utiliser procédures, il faudra regarder et se sentir maladroit). Alors
, si vous pouvez travailler avec cette date fixe plages vous pouvez même remplacer la table à la requête, comme ce
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
qui produira 10.000 lignes allant de 1 à 10 000 et il ne sera pas terriblement inefficace. Donc, à la fin, c'est faisable dans une seule requête.
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 Je l'ai fait dans le code (en dehors de SQL) mais très intéressant de voir si des solutions propres SQL uniquement surgiront – Tomas
Ceci est un souvent posée et répondu à la question sur le SO (recherche de 'jour 'et' [sql] 'ou' [mysql] '). Voir, par exemple, http://stackoverflow.com/questions/1046865/mysql-select-all-dates-in-a-range-even-if-no-records-present – pilcrow
@pilcrow: c'est une question fréquemment posée, mais la réponse liée n'est pas particulièrement exhaustive dans les détails. @OP: normalement ce genre de chose n'est pas si facile dans les bases de données qui ne supportent pas le SQL récursif; J'ai quand même posté un peu de SQL (avec quelques problèmes, mais ça pourrait être utile) – Unreason