1. 原始數據:
2020-09-01 2020-09-11 2020-09-07 2020-09-20 2020-09-24 2020-10-25 2020-09-25 2020-10-11 2020-09-26 2020-09-27 2020-09-30 2020-10-25 2020-10-30 2020-11-30 2020-10-31 2020-11-29 2020-10-31 2020-12-01
2. 需求
公司在某一時期搞一系列活動,在活動周期內,計算客戶在這段時間內是否連續每天都參加活動
比如一到五月,每個月隔幾天就出新的活動,比如A活動有十天[09-01,09-11],B活動有五天[09-07,09-20],中間有重疊的日期,這樣算客戶[09-01,09-20]這段時間都是在參加活動
需求需要將這個客戶的參加活動時間周期統計出來
3. 分析
這里面主要牽扯兩個問題:一,幾個時間段日期有重疊,二,單獨沒重疊的日期。
判斷日期是否有重疊,根據開始日期start_time進行升序排序,取出每個區間中開始日期最小值和結束日期最大值
首先我們需要將所屬同一區間的數據整理出來,使用開窗函數依次對比開始日期start_time和結束日期 end_time,找到start_time大於之前end_time中的最大值的記錄,打標記為1
這樣就將區間區分出來了
然后取區間中的最小start_time和最大end_time即可
上代碼:
with a_starts as ( --計算區間並打上結束標記 select start_time , end_time , CASE when start_time > max(lag_end_time) over( order by start_time, end_time rows between unbounded preceding and current row ) then 1 else 0 END a_start from ( select start_time, end_time, lag(start_time, 1) over(order by start_time, end_time) lag_start_time, lag(end_time, 1) over(order by start_time, end_time) lag_end_time from a ) t1 ) , a1 as ( --將區間內標記求和,作為分組依據 select start_time, end_time, sum(a_start) over( order by start_time, end_time rows between unbounded preceding and current row ) grp from a_starts ) select min(start_time) start_time, max(end_time) end_time from a1 group by grp order by 1, 2;
結果:
感謝知乎博主的分享:https://zhuanlan.zhihu.com/p/68630630