MySQL之按年、月、日統計數據並進行數據填充
一、準備工作:建表
- 建表sql:
CREATE TABLE num ( i INT ( 11 ) NULL DEFAULT NULL COMMENT '序號' ) ENGINE = INNODB CHARACTER
SET = utf8 COLLATE = utf8_general_ci COMMENT = '“存儲數字工具表”' ROW_FORMAT = Dynamic;
- 設置數據:
INSERT INTO num (i) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
二、方法闡述
使用mysql進行按日期分組統計數據,並進行填充數據比較簡單,在這裏對該方法進行一個先後順序的講解:
1. 首先,根據笛卡爾乘積(也就是CROSS JOIN),獲取0-99的數據列表。
- SQL語句:
SELECT
n1.i + n10.i * 10 AS id
FROM
num n1
CROSS JOIN num AS n10
執行效果:查詢出來的就是0至99的數據,如下圖所示
如果對數據的需求量大,可使用0-999的數據列表,SQL語句爲:
SELECT
n1.i + n10.i * 10 + n100.i * 100 AS id
FROM
num n1
CROSS JOIN num AS n10
CROSS JOIN num AS n100
2. 獲取時間段(這裏舉例獲取9月份的所有日期)
這裏使用ADDDATE(expr,days)日期函數,其中expr爲指定日期,days爲數字,正數爲增加,負數爲減少。
- 獲取九月份的所有日期SQL:
SELECT
adddate( '2018-09-01', numlist.id ) AS 'date'
FROM
( SELECT n1.i + n10.i * 10 AS id FROM num n1 CROSS JOIN num AS n10 ) AS numlist
WHERE
adddate( '2018-09-01', numlist.id ) <= date_add( '2018-09-01', INTERVAL 1 MONTH )
- 執行效果:
- 注意:因爲sql函數查詢的是從2018年9月1日起,到一個月後的數據,所以會多計算一天,可在代碼中對結果進行處理。
3. 原sql統計結果
- 我們進行數據統計時,會面臨某一天沒有數據的情況。這裏爲了方便,我們使用 ‘result_jay‘這個單詞作爲原SQL語句的標識
原SQL-‘result_jay’的統計結果,如下圖:
可以觀察到,在我們原來的SQL數據統計結果: 1.統計結果不精確(例子是隻需統計18年9月份數據);2.九月份很多天是沒有數據的
4. 完整SQL
- 此處爲完整SQL,爲上述步驟結合。先獲取查詢的時間段範圍,然後左關聯我們的統計結果–》大體就是:SELECT
[結果列]
FROM[時間段範圍]
LEFT JOIN[原SQL統計結果]
ON[時間段範圍.日期]
=[原SQL統計結果.日期]
ORDER BY[時間段範圍.日期]
- SQL語句:
SELECT
temp.date AS 'name',
COALESCE ( u.num, 0 ) 'y'
FROM
(
SELECT
adddate( '2018-09-01', numlist.id ) AS 'date'
FROM
( SELECT n1.i + n10.i * 10 AS id FROM num n1 CROSS JOIN num AS n10 ) AS numlist
WHERE
adddate( '2018-09-01', numlist.id ) <= date_add( '2018-09-01', INTERVAL 1 MONTH )
) temp
LEFT JOIN ( result_jay ) u ON temp.date = u.date
ORDER BY
temp.date
- 執行效果
COALESCE ( u.num, 0 )函數是用來填充結果,若查詢爲null,則賦值0
5. 按年統計(提供三個參數值,如2018年的數據統計,則參數分別爲:2018-01-01,2018-01-01,2018-12-01)
同理,有區分的就是時間段範圍,即完整SQL中from後的主體部分,這裏就不貼完整SQL了。
- 時間段SQL
SELECT
adddate( '2018-01-01', INTERVAL numlist.id MONTH ) AS 'date'
FROM
(
SELECT
*
FROM
( SELECT n1.i + n10.i * 10 AS id FROM num n1 CROSS JOIN num AS n10 ) a
WHERE
a.id <= 11
) AS numlist
WHERE
adddate( '2018-01-01', INTERVAL numlist.id MONTH ) <= '2018-12-01
6. 按周統計
需求爲:選中一個日期,獲取該日期所在周的數據統計。即選擇2018-09-11 星期二,那麼最終的數據統計範圍應爲:2018-09-10 星期一至2018-09-16 星期日七天的數據
時間段SQL:
SELECT
adddate( ( SELECT subdate( '2018-09-11', date_format( '2018-09-11', '%w' ) - 1 ) ), INTERVAL numlist.id DAY ) AS 'date'
FROM
(
SELECT
*
FROM
( SELECT n1.i + n10.i * 10 AS id FROM num n1 CROSS JOIN num AS n10 ) a
WHERE
a.id <= 6
) AS numlist
WHERE
adddate( ( SELECT subdate( '2018-09-11', date_format( '2018-09-11', '%w' ) - 1 ) ), INTERVAL numlist.id DAY ) <= ( SELECT subdate( '2018-09-11', date_format( '2018-09-11', '%w' ) - 9 ) )
- 執行結果:
暫時記錄到這裏,2018年9月10日16:33:42。