首先介紹一個函數:YEARWEEK(date
[,mode
])
主要說明一下后面的可選參數mode,這個參數就是指定一周里面哪一天是第一天。
默認一周是從周日開始,這顯然不太符合我們的要求。要指定每周從周一開始的話,mode=1就好了。
下圖為該參數的說明:
接下來進入正題,直接上SQL吧
SELECT date_format(lastWeek.`timeDay`,'%Y-%m-%d') as 'timeDay' FROM ( select DATE_SUB(NOW(),interval 13 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 12 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 11 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 10 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 9 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 8 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 7 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 6 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 5 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 4 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 3 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 2 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 1 day) as 'timeDay' ) as lastWeek WHERE YEARWEEK(lastWeek.`timeDay`,1) = YEARWEEK(NOW(),1)-1
為什么說這是個土方呢,哈哈!首先看上去莫名的土,理解一下邏輯如下:
假如今天是周一,我要得出上周一和上周日的日期,很簡單: 上周一距離今天7天=select DATE_SUB(NOW(),interval 7 day); 上周日距離今天1天=select DATE_SUB(NOW(),interval 1 day); 沒毛病,那如果今天是周日呢? 上周一距離今天13天=select DATE_SUB(NOW(),interval 13 day); 上周日距離今天7天=select DATE_SUB(NOW(),interval 7 day); 沒錯,這里就是查詢出來上周所有可能的日期,因為這個問題的難點就是 我們不能指定當前的日期。 查詢出來之后在結合MySql的函數YEARWEEK,就可以得出上周的日期了
我寫這個的SQL的原因,是因為有這么個需求:要統計上周每天的注冊人數,以柱狀圖的形式展現。
要是直接使用
SELECT DATE_FORMAT(regist_date,'%Y-%m-%d') '注冊時間',COUNT(*) as '注冊人數' FROM t_user WHERE YEARWEEK(regist_date,1) = YEARWEEK(NOW(),1)-1 GROUP BY DATE_FORMAT(regist_date,'%Y-%m-%d')
會出現如果有一天沒有注冊人數的話,這一天就沒有數據,產品的需求呢是沒有注冊人數的話顯示為0。
於是就有了下面的寫法
SELECT t1.timeDay as '日期',t2.`注冊人數` FROM ( SELECT date_format(lastWeek.`timeDay`,'%Y-%m-%d') as 'timeDay' FROM ( select DATE_SUB(NOW(),interval 13 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 12 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 11 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 10 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 9 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 8 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 7 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 6 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 5 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 4 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 3 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 2 day) as 'timeDay' UNION ALL select DATE_SUB(NOW(),interval 1 day) as 'timeDay' ) as lastWeek WHERE YEARWEEK(lastWeek.`timeDay`,1) = YEARWEEK(NOW(),1)-1 ) as t1 LEFT JOIN ( SELECT DATE_FORMAT(regist_date,'%Y-%m-%d') '注冊時間',COUNT(*) as '注冊人數' FROM t_user WHERE YEARWEEK(regist_date,1) = YEARWEEK(NOW(),1)-1 GROUP BY DATE_FORMAT(regist_date,'%Y-%m-%d') ) as t2 ON t1.timeDay = t2.`注冊時間` ORDER BY t1.timeDay
這樣就搞定了。你還可以以這種方法查出上個月的日期哦。
希望能幫到你~