寫博客真實個費時費力的差事,好佩服那些博客閱讀幾十上百萬的人。今天研究了半天按照日期分組統計,沒有數據就為空了,我要讓他顯示0呀。想了辦法,都沒有找到一個好的,解決方案,然后用了一個很low的方法實現了,還是把它記錄下來。方法是用於mysql,與開發語言無關。
1、案例中的數據結構和數據如下

2、在沒有解決的時候,是這樣的
SELECT date(downtime) AS dday, count(*) AS num FROM re_device GROUP BY dday
得到如下結果,如果那天沒有數據,那麽就會沒有記錄
我們看到,時間不連續,沒有2016-3-05這一天的,這樣本來不是問題,但是,我拿出來的數據,還要畫出圖表呀,沒有當然不行,我們需要的是下面這個樣子的。

簡單的說就是,沒有數據,就要補充一個0.
3、下面我們講實現
我們要生成一個日歷的表,然后和原來的數據,聯合查詢,說到這里,大家就知道很low了,但是,限於我水平有限,研究這個問題,半天,這個是我找到的比較好的一種實現方式。如果你又更好的,也請你給我說下。
執行下面的sql,直接誒生成日歷的表(calendar)
CREATE TABLE num (i int);-- 創建一個表用來儲存0-9的數字
INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);-- 生成0-9的數字,方便以后計算時間
CREATE TABLE if not exists calendar(datelist date); -- 生成一個存儲日期的表,datalist是字段名
-- 這里是生成並插入日期數據
INSERT INTO calendar(datelist) SELECT
adddate(
( -- 這里的起始日期,你可以換成當前日期
DATE_FORMAT("2016-1-1", '%Y-%m-%d')
),
numlist.id
) AS `date`
FROM
(
SELECT
n1.i + n10.i * 10 + n100.i * 100 + n1000.i * 1000+ n10000.i * 10000 AS id FROM
num n1
CROSS JOIN num AS n10
CROSS JOIN num AS n100
CROSS JOIN num AS n1000
CROSS JOIN num AS n10000
) AS numlist;
這里我用了100000條記錄,算出來到2289年了,完全夠用了,到那個時候,出問題,我也管不了了。
完成之后,請刪除num的零時表
4、聯合查詢
SELECT
date(dday) ddate,
count(*) - 1 as num
FROM
(
SELECT
datelist as dday
FROM
calendar
-- 這里是限制返回最近30天的數據
where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date
(datelist)&&date(datelist)<=CURDATE()
UNION ALL
SELECT
downtime
FROM
re_device
) a
GROUP BY ddate
好了,到這里,基本就完成了這個查詢,出來的數據,我還是比較滿意的。
5、其他解決方法
當然,應該還有其他的解決方案,但是博主就沒有去寫了,有時間可以去寫一下。
我用的spring mvc,所以,也還是可以在java代碼中補充完整的,因為數據返回的是個map對象,那麽我們要遍歷這個對象,直接用calendar對象,生成日期作為key來遍歷,如果沒有數據,就put進去一個0,然后在限制一下,需要多少天的,就可以了。數據就完整了。
但是這樣也有一個問題,那就是map里的數據順序會有問題,所以,使用的時候,也必須是生成calendar對象,然后構造出來日期作為key來遍歷。或者用Collections.sort()排序一下。
我個人覺得,還是上數據直接生成得比較好一點。
