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
