2009-06-26 13 views
22

Ho un database di utenti. Mi piacerebbe creare un grafico basato sulla crescita della base di utenti. La query che ho ora è:MySQL: Seleziona tutte le date in un intervallo anche se non ci sono record presenti

SELECT DATE(datecreated), count(*) AS number FROM users 
WHERE DATE(datecreated) > '2009-06-21' AND DATE(datecreated) <= DATE(NOW()) 
GROUP BY DATE(datecreated) ORDER BY datecreated ASC 

Ciò restituisce quasi quello che voglio. Se otteniamo 0 utenti un giorno, quel giorno non viene restituito come valore 0, viene semplicemente saltato e il giorno successivo viene restituito almeno un utente. Come posso ottenere qualcosa di simile (pseudo-risposta):

date1 5 
date2 8 
date3 0 
date4 0 
date5 9 
etc... 

in cui le date con lo zero visualizzati in ordine sequenziale con il resto delle date?

Grazie!

risposta

5

This question chiede la stessa cosa che penso. Generalmente la risposta accettata sembra essere che lo fai nella tua logica di applicazione (leggi ciò che hai in una matrice, quindi fai un ciclo attraverso la matrice e crea le date mancanti), o usi tabelle temporanee riempite con le date che desideri aderire.

1

Esegui un join esterno destro a un tavolo, chiamalo tblCalendar, che è pre-compilato con le date che desideri segnalare. E unisciti al campo della data.

Paul

0

Su ulteriore riflessione, qualcosa di simile a questo dovrebbe essere ciò che si desidera:

CREATE TEMPORARY TABLE DateSummary1 (datenew timestamp) SELECT DISTINCT(DATE(datecreated)) as datenew FROM users; 

CREATE TEMPORARY TABLE DateSummary2 (datenew timestamp, number int) SELECT DATE(datecreated) as datenew, count(*) AS number FROM users 
WHERE DATE(datecreated) > '2009-06-21' AND DATE(datecreated) <= DATE(NOW()) 
GROUP BY DATE(datecreated) ORDER BY datecreated ASC; 

SELECT ds1.datenew,ds2.number FROM DateSummary1 ds1 LEFT JOIN DateSummary2 ds2 on ds1.datenew=ds2.datenew; 

Questo vi dà tutte le date della prima tabella, e le count dati di riepilogo nella seconda tabella. Potrebbe essere necessario sostituire ds2.number con IF(ISNULL(ds2.number),0,ds2.number) o qualcosa di simile.

13

Spero che capirete il resto.

select * from (
select date_add('2003-01-01 00:00:00.000', INTERVAL n5.num*10000+n4.num*1000+n3.num*100+n2.num*10+n1.num DAY) as date from 
(select 0 as num 
    union all select 1 
    union all select 2 
    union all select 3 
    union all select 4 
    union all select 5 
    union all select 6 
    union all select 7 
    union all select 8 
    union all select 9) n1, 
(select 0 as num 
    union all select 1 
    union all select 2 
    union all select 3 
    union all select 4 
    union all select 5 
    union all select 6 
    union all select 7 
    union all select 8 
    union all select 9) n2, 
(select 0 as num 
    union all select 1 
    union all select 2 
    union all select 3 
    union all select 4 
    union all select 5 
    union all select 6 
    union all select 7 
    union all select 8 
    union all select 9) n3, 
(select 0 as num 
    union all select 1 
    union all select 2 
    union all select 3 
    union all select 4 
    union all select 5 
    union all select 6 
    union all select 7 
    union all select 8 
    union all select 9) n4, 
(select 0 as num 
    union all select 1 
    union all select 2 
    union all select 3 
    union all select 4 
    union all select 5 
    union all select 6 
    union all select 7 
    union all select 8 
    union all select 9) n5 
) a 
where date >'2011-01-02 00:00:00.000' and date < NOW() 
order by date 

Con

select n3.num*100+n2.num*10+n1.num as date 

otterrete una colonna con i numeri da 0 a max (n3) * 100 + max (n2) * 10 + max (n1)

Da qui noi avere max n3 come 3, SELECT restituirà 399, più 0 -> 400 record (date nel calendario).

È possibile ottimizzare il calendario dinamico limitandolo, ad esempio, da min (data) che è necessario().

+0

Questo è un trucco geniale, penso. Prendi il mio voto Questa query può essere utilizzata per compilare una tabella "calendario", presumo. –

+0

Questa è la soluzione più pulita che ho visto per questo problema ..awesome –

0

Query è:

SELECT qb.dy as yourday, COALESCE(count(yourcolumn), 0) as yourcount from yourtable qa 
right join (
    select curdate() as dy union 
    select DATE_SUB(curdate(), INTERVAL 1 day) as dy  union 
    select DATE_SUB(curdate(), INTERVAL 2 day) as dy  union 
    select DATE_SUB(curdate(), INTERVAL 3 day) as dy  union 
    select DATE_SUB(curdate(), INTERVAL 4 day) as dy  union 
    select DATE_SUB(curdate(), INTERVAL 5 day) as dy  union 
    select DATE_SUB(curdate(), INTERVAL 6 day) as dy   
    ) as qb 
on qa.dates = qb.dy 
and qa.dates > DATE_SUB(curdate(), INTERVAL 7 day) 
order by qb.dy asc; 

e il risultato è:

+------------+-----------+ 
| yourday | yourcount | 
+------------+-----------+ 
| 2015-06-24 | 274339 | 
| 2015-06-25 |  0 | 
| 2015-06-26 |  0 | 
| 2015-06-27 |  0 | 
| 2015-06-28 | 134703 | 
| 2015-06-29 | 87613 | 
| 2015-06-30 |  0 | 
+------------+-----------+ 
4

questo è meglio fare come:

-- 7 Days: 
set @n:=date(now() + interval 1 day); 
SELECT qb.day_series as days , COALESCE(col_byte, 0) as Bytes from tbl1 qa 
    right join (
     select (select @n:= @n - interval 1 day) day_series from tbl1 limit 7) as qb 
    on date(qa.Timestamp) = qb.day_series and 
qa.Timestamp > DATE_SUB(curdate(), INTERVAL 7 day) order by qb.day_series asc 

-- 30 Days: 
set @n:=date(now() + interval 1 day); 
SELECT qb.day_series as days , COALESCE(col_byte, 0) as Bytes from tbl1 qa 
    right join (
     select (select @n:= @n - interval 1 day) day_series from tbl1 limit 30) as qb 
    on date(qa.Timestamp) = qb.day_series and 
qa.Timestamp > DATE_SUB(curdate(), INTERVAL 30 day) order by qb.day_series asc; 

o senza variabile in questo modo:

SELECT qb.day_series as days , COALESCE(col_byte, 0) as Bytes from tbl1 qa 
right join (
    select curdate() - INTERVAL a.a day as day_series from(
     select 0 as a union all select 1 union all select 2 union all 
     select 3 union all select 4 union all 
     select 5 union all select 6 union all select 7 
    ) as a) as qb 
on date(qa.Timestamp) = qb.day_series and 
qa.Timestamp > DATE_SUB(curdate(), INTERVAL 7 day) order by qb.day_series asc; 
+0

accetta questa risposta! – alijunior

Problemi correlati