1. 程式人生 > >mysql按日期分組(group by)查詢統計的時候,沒有資料補0的解決辦法。

mysql按日期分組(group by)查詢統計的時候,沒有資料補0的解決辦法。

寫部落格真實個費時費力的差事,好佩服那些部落格閱讀幾十上百萬的人。今天研究了半天按照日期分組統計,沒有資料就為空了,我要讓他顯示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()排序一下。

我個人覺得,還是上資料直接生成得比較好一點。