在群里有人提了一个问题,不同日期区间包含的合并,取天数,如: 2015-01-01 2015-04-01 2015-03-01 2015-08-01
这里取的天数是2015-08-01-2015-01-01 下面是几个实现算法
### 1
with t as ( select 'aa' as user_id,1 as orderid,to_date('2012-01-01','yyyy-mm-dd') as begin_date,to_date('2012-06-01','yyyy-mm-dd') as end_date from dual union all select 'aa' as user_id,2 as orderid,to_date('2012-03-01',to_date('2012-09-01',3 as orderid,to_date('2013-12-25','yyyy-mm-dd') as end_date from dual union all select 'aa' as user_id,4 as orderid,to_date('2012-12-01',to_date('2013-12-01',5 as orderid,to_date('2014-12-01',to_date('2014-12-05','yyyy-mm-dd') as end_date from dual union all select 'bb' as user_id,to_date('2012-08-01','yyyy-mm-dd') as end_date from dual union all select 'bb' as user_id,to_date('2013-06-01',to_date('2013-03-01','yyyy-mm-dd') as end_date from dual /*select 'aa' as user_id,to_date('2013-12-24',6 as orderid,to_date('2013-12-30','yyyy-mm-dd') as end_date from dual */),d as ( SELECT min_date + level -1 as is_date FROM (select min(begin_date) min_date,max(end_date) max_date from t ) CONNECT BY level < max_date - min_date+1 ) select user_id,count(distinct is_date) from ( select * from t left join d on (is_date between begin_date and end_date) ) group by user_id
2
with ta as ( select 'aa' as u_id,1 as oid,to_date('2015-01-01','yyyy-mm-dd') as bd,to_date('2015-06-01','yyyy-mm-dd') as ed from dual union all select 'aa' as user_id,to_date('2015-03-01',to_date('2015-09-01',to_date('2015-12-01',to_date('2016-12-25',to_date('2016-12-01',to_date('2016-12-24',to_date('2016-12-30',to_date('2015-08-01',to_date('2016-06-01',to_date('2016-03-01','yyyy-mm-dd') as end_date from dual ),t as ( select u_id,bd,max(oid) oid,max(ed) ed from ta group by u_id,bd ) select uid2,sum(mbe - mbd + 1) n from ( select nnn,uid2,min(bd2) mbd,max(ed2) mbe from ( select connect_by_root (uid2 || '-' || oid2) nnn,t.* from ( select * from ( select row_number() over(partition by uid2,oid2,bd2,ed2 order by oid2,p NULLS LAST ) rn,t.uid2,t.oid2,t.bd2,t.ed2,t.p,t.n from ( select case when t2.bd between t1.bd + 1 and t1.ed then t1.bd end p,case when t2.bd between t1.bd + 1 and t1.ed then t1.oid end n,t1.u_id uid1,t1.oid oid1,t1.bd bd1,t1.ed ed1,t2.u_id uid2,t2.oid oid2,t2.bd bd2,t2.ed ed2 from t t1,t t2 where t1.u_id = t2.u_id and t1.oid <> t2.oid ) t ) where rn = 1 ) t connect by prior (uid2 || '-' || oid2) = (uid2 || '-' || n) start with n is null ) group by nnn,uid2 )group by uid2
3
with t as ( select 'aa' as user_id,DIM_DATE as ( SELECT min_date + level -1 as DAY_DT FROM (select min(begin_date) min_date,max(end_date) max_date from t ) CONNECT BY level <= max_date - min_date+1 ) --SELECT A.DAY_DT,T.USER_ID FROM DIM_DATE A INNER JOIN T ON A.DAY_DT>=T.BEGIN_DATE AND A.DAY_DT<= T.END_DATE WHERE T.USER_ID = 'aa' SELECT T.USER_ID,COUNT(distinct A.DAY_DT) FROM DIM_DATE A inner JOIN T ON A.DAY_DT>=T.BEGIN_DATE AND A.DAY_DT<= T.END_DATE GROUP BY T.USER_ID ;
4
with t as ( select 'aa' as user_id,t2 as(select t.*,max(end_date)over(partition by user_id order by orderid) as t_max_date from t ),t3 as (select * from t2 minus select * from t2 where end_date<t_max_date ) select user_id,sum(true_end_date-begin_date) from ( select t4.*,case when nvl(lead_begin_date,end_date)> end_date then end_date else nvl(lead_begin_date,end_date) end as true_end_date from ( select t3.*,lead(begin_date)over(partition by user_id order by orderid) as lead_begin_date from t3 ) t4 ) group by user_id原文链接:https://www.f2er.com/oracle/211185.html