SQL實現日期自動填充
在使用SQL進行數據處理時,經常會遇到需要補齊日期的需求,今天聊一聊幾個主流數據庫的實現方式。
下面以生成2021-09-01到2021-09-30之間所有日期為例進行說明
Oracle
connect by的遞歸查詢還是比較強大的,實現起來也比較簡單
SELECT TO_DATE('2021-08-31', 'yyyy-mm-dd') + ROWNUM as date_list
FROM DUAL
CONNECT BY ROWNUM <= 30;
MySQL
- 在MySQL8之前的版本,通過先生成序號列表,再使用起始日期增加相應天數來實現
SELECT date_add('2021-09-01', INTERVAL d_num DAY) date_list
FROM (
-- 使用@變量的形式,得到序號列表
SELECT @num := @num + 1 as d_num
from
-- 通過兩個臨時表做笛卡爾積,得到一個記錄數為兩個表乘積的數據
-- 此處為5*6=30天
(SELECT 1 UNION SELECT 2 UNION
SELECT 3 UNION SELECT 4 UNION SELECT 5) t1,
(SELECT 1 UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) t2,
-- 聲明從-1開始
(SELECT @num := -1) a
) a
- 在MySQL8以后,可以通過遞歸語法實現
WITH RECURSIVE cte (d) AS
(SELECT '2021-09-01'
UNION ALL
SELECT d + INTERVAL 1 DAY
FROM cte
WHERE d + INTERVAL 1 DAY <= '2021-09-30')
SELECT *
FROM cte
ORDER BY cte.d;
PostgreSQL
實現起來比較簡單粗暴,直接使用generate_series函數生成
select generate_series(
'2021-09-01'::date,
'2021-09-30',
'1 day') date_list;
Hive 函數
在Hive上面的實現相對復雜一些,實現思路是構建出起始日期需要增加天數,然后使用起始日期增加相應的天數實現日期補齊
-
使用datediff計算起始日期與結束日期的日期差的天數n
-
使用repeat生成一個字符串s,字符串內容為重復某字符n遍
-
使用split將字符串s拆分成數組a
-
使用posexplode將數組a轉為n行帶序號的數據
posexplode說明:behaves like explode for arrays, but includes the position of items in the original array
-
通過date_add函數,從起始日期加上序號達到日期補齊
注:本SQL是在Hive3.1.2中執行
select date_add('2021-09-01', a.pos) as d
from (select posexplode(
split(
repeat('m', 29)
, 'm')
)) a
歡迎關注微信公眾號:數據研發技術,干貨滿滿
