2015-01-15 89 views
2

我打算爲客戶展開我的START END日期,如下所示。如果日期範圍連續,我將合併這些記錄。其他明智我會保持它作爲這樣 EG:僅限特定記錄的子句組

Input 
Customer START END 
A  2000 2001 
A  2001 2007 
A  2009 2010 
A  2011 2015 

Expected Output 
A  2000 2007 
A  2009 2010 
A  2011 2015 

使用分析功能,我能夠連續日期標記的記錄:

--TAG = 1 means continuous 
select A *, 
CASE WHEN LEAD (START) OVER (PARTITION BY CUSTOMER ORDER BY START,END) = END 
OR LAG (END_DT) OVER (PARTITION BY CUSTOMER ORDER BY START,END) = START 
THEN 1 ELSE 0 END AS CONT_FLG 
From TABLE CUSTOMER 

Customer START END CONT_FLG 
A  2000 2001 1 
A  2001 2007 1 
A  2009 2010 0 
A  2011 2015 0 

但我不能用分鐘(START)和MAX進行(END)分組,因爲它將合併非連續值。任何好的建議

回答

1

如果您獲得實際的超前/滯後的日期,而不是0/1,那麼你得到的東西是這樣的:

select t.*, 
    case when lag(end_dt) over (partition by customer order by start_dt) 
    = start_dt then null else start_dt end as adj_start_dt, 
    case when lead(start_dt) over (partition by customer order by start_dt) 
    = end_dt then null else end_dt end as adj_end_dt 
from t42 t 
order by customer, start_dt; 

CUSTOMER START_DT  END_DT ADJ_START_DT ADJ_END_DT 
-------- ---------- ---------- ------------ ---------- 
A    2000  2001   2000    
A    2001  2003       
A    2003  2007     2007 
A    2009  2010   2009  2010 
A    2011  2015   2011  2015 

我已經將你的第二條記錄分成兩個相鄰的記錄以便生效,這樣在這裏有一行與bot調整日期爲空。然後,您可以刪除那些既空,那些反映完全是一個範圍內的記錄,你留下了各個時期的開始和結束日期:

select * 
from (
    select t.*, 
    case when lag(end_dt) over (partition by customer order by start_dt) 
     = start_dt then null else start_dt end as adj_start_dt, 
    case when lead(start_dt) over (partition by customer order by start_dt) 
     = end_dt then null else end_dt end as adj_end_dt 
    from t42 t 
) 
where adj_start_dt is not null or adj_end_dt is not null 
order by customer, start_dt; 

CUSTOMER START_DT  END_DT ADJ_START_DT ADJ_END_DT 
-------- ---------- ---------- ------------ ---------- 
A    2000  2001   2000    
A    2003  2007     2007 
A    2009  2010   2009  2010 
A    2011  2015   2011  2015 

然後你可以摺疊那些值爲空,相鄰行(帶有超前/滯後)現在是相關的:

select distinct customer, 
    case when adj_start_dt is null then 
    lag(adj_start_dt) over (partition by customer order by start_dt) 
    else adj_start_dt end as grp_start_dt, 
    case when adj_end_dt is null then 
    lead(adj_end_dt) over (partition by customer order by start_dt) 
    else adj_end_dt end as grp_end_dt 
from (
    select t.*, 
    case when lag(end_dt) over (partition by customer order by start_dt) 
     = start_dt then null else start_dt end as adj_start_dt, 
    case when lead(start_dt) over (partition by customer order by start_dt) 
     = end_dt then null else end_dt end as adj_end_dt 
    from t42 t 
) 
where adj_start_dt is not null or adj_end_dt is not null 
order by customer, grp_start_dt; 

CUSTOMER GRP_START_DT GRP_END_DT 
-------- ------------ ---------- 
A    2000  2007 
A    2009  2010 
A    2011  2015 

SQL Fiddle demo

+0

這真棒..好學習..感謝很多 – Awknewbie

1

試着這麼做

select customer, min(start), min(end) 
from 
(
select A *, 
CASE WHEN LEAD (START) OVER (PARTITION BY CUSTOMER ORDER BY START,END) = END 
OR LAG (END_DT) OVER (PARTITION BY CUSTOMER ORDER BY START,END) = START 
THEN 1 ELSE 0 END AS CONT_FLG 
From TABLE CUSTOMER 
) 
group by customer, cont_flg, case when cont_flg=0 then start end