2009-06-26 86 views
22

我有一個用戶數據庫。我想創建一個基於用戶基數增長的圖表。查詢我現在是:MySQL:選擇範圍內的所有日期即使沒有記錄存在

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 

這將返回幾乎我想要的東西。如果我們有一天獲得0個用戶,那麼這一天不會返回爲0值,它會被跳過,並且返回至少有一個用戶的第二天。我怎樣才能獲得類似的信息(僞響應):

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

其中零日期的順序顯示與日期的休息嗎?

謝謝!

回答

5

This question問我想的是同樣的事情。一般來說,接受的答案似乎是你要麼在你的應用程序邏輯中完成它(讀入數組中的內容,然後循環訪問數組並創建缺失的日期),或者使用填充了你希望的日期的臨時表加入。

1

做了右外連接到一個表,把它tblCalendar,即預先填入您要舉報的日期。並加入日期字段。

保羅

0

在進一步的思考,這樣的事情應該是你想要什麼:

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; 

這給你所有的日期在第一個表,並在第二個表count彙總數據。您可能需要將ds2.number替換爲IF(ISNULL(ds2.number),0,ds2.number)或類似的東西。

13

我希望你能弄清楚其餘的。

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 

隨着

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

你會得到與數字的列從0到最大(N3)* 100 + MAX(N2)* 10 + MAX(N1)

因爲我們在這裏將最大n3設置爲3,SELECT將返回399,再加上0 - > 400條記錄(日曆中的日期)。

您可以通過限制它來調整動態日曆,例如,從min(日期)到現在()。

+0

我認爲這是一個絕妙的訣竅。得到我的投票。我猜這個查詢可以用來填充「日曆」表。 – 2013-07-05 21:23:46

+0

這是我見過的最乾淨的解決方案。真棒 – 2016-06-08 11:10:08

0

查詢:

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; 

,其結果是:

+------------+-----------+ 
| 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

這是更好地做到爲:

-- 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; 

或不變量是這樣的:

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;