Es ist ein Ansatz, das kann dies in reinem SQL tun, aber es hat Einschränkungen.
Zuerst müssen Sie eine Zahlenfolge 1,2,3 haben ... n als Zeilen (select row from rows
Rückkehr annehmen kann).
Dann können Sie linken beitreten und zu Daten basierend auf Anzahl der Tage zwischen min und max konvertieren.
select @min_join_on := (select min(join_on) from user);
select @no_rows := (select datediff(max(join_on), @min_join_on) from user)+1;
geben Sie die gewünschte Anzahl der Zeilen, die dann können Sie
select adddate(@min_join_on, interval row day) from rows where row <= @no_rows;
zu
verwenden eine erforderliche Folge von Daten, an denen zurückkehren, dann können Sie einen linken trete zurück an den Benutzer-Tabelle .
Die Verwendung von Variablen kann vermieden werden, wenn Sie Unterabfragen verwenden, die ich aus Gründen der Lesbarkeit abbrach.
Nun ist das Problem, dass die Anzahl der Zeilen in der Tabelle rows
dann @no_rows größer sein muss. Für 10.000 Zeilen können Sie mit Datumsbereichen von bis zu 27 Jahren arbeiten, mit 100.000 Zeilen können Sie mit Datumsbereichen von bis zu 273 Jahren arbeiten (das fühlt sich wirklich schlecht an, aber ich befürchte, wenn Sie nicht gespeichert verwenden möchten Verfahren wird es peinlich aussehen und fühlen müssen).
Also, wenn Sie mit einer solchen festen Termin arbeiten kann, reicht Ihnen auch die Tabelle mit der Abfrage ersetzen können, wie diese
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
, die von 1 bis 10.000 gehen 10.000 Zeilen erzeugen, und es wird nicht sein furchtbar ineffizient.
So am Ende ist es in einer einzigen Abfrage machbar.
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 Ich habe es in Code getan (außerhalb von SQL), aber sehr interessant zu sehen, ob einige sauberen SQL-only Lösungen – Tomas
Pop-up Dies ist ein häufig gestellte und beantwortete Frage auf SO (Suche nach 'date 'und' [sql] 'oder' [mysql] '). Siehe zB http://stackoverflow.com/questions/1046865/mysql-select-all-dates-in-a-range-even-if-no-records-present – pilcrow
@pilcrow: es ist eine häufig gestellte Frage, aber die verknüpfte Antwort ist in den Details nicht besonders erschöpfend. @OP: normalerweise ist diese Art von Sache nicht so einfach in Datenbanken, die rekursives SQL nicht unterstützen; noch habe ich etwas SQL geposted (mit einigen Problemen, aber es könnte nützlich sein) – Unreason