2015-10-21 12 views
2

我有一張表,其結構如下,我試圖在兩天之間找到TAT(週轉時間)。但是,這樣做的重疊日子裏,我無法找到實際的TAT通過比較兩個日期列來確定實際的TAT(週轉時間)

Appln No  Start Date End Date 
1001009  01-10-15 06-10-15 
1001009  02-10-15 04-10-15 
1001009  03-10-15 04-10-15 
1001009  03-10-15 05-10-15 
1001009  04-10-15 07-10-15 
1001009  09-10-15 10-10-15 
1001009  12-10-15 16-10-15 
1001009  14-10-15 17-10-15 

從上面的樣本數據中去除重疊的日期後,輸出會在下面的格式 -

Appln No Start Date End Date 
1001009  01-10-15 07-10-15 
1001009  09-10-15 10-10-15 
1001009  12-10-15 17-10-15 

由於我是一名sql初學者,使用oracle sql developer,我發現很難將上面的邏輯寫入代碼。在這個問題上有任何建議都是歡迎的。

回答

1

試試這個:

select t1.* from myTable t1 
inner join myTable t2 
on t2.StartDate > t1.StartDate and t2.StartDate < t1.EndDate 
+0

如果「Appln」只有一條記錄,則不起作用。 – JimmyB

1

這是一個棘手的查詢。您需要通過分配分組ID來確定重疊的組。一種方法是找到重疊組的起始位置,然後累積每條記錄之間的起始數。

以下內容假定您的表具有主鍵(缺少更好的名稱稱爲id)。

這使聚合得到你想要的機會:

select ApplnNo, min(start), max(end) 
from (select t.*, 
      sum(IsGroupStart) over (partition by ApplnNo order by start) as grp 
     from (select t.*, 
        (case when exists (select 1 
             from t t2 
             where t2.end >= t.start and t2.start <= t.end and 
              t2.id <> t.id 
            ) 
         then 0 else 1 
        end) as IsGroupStart 
      from t 
      ) t 
    ) t 
group by ApplnNo, grp; 

有一些細微差別。 exists確切的最裏面的子查詢取決於你如何定義重疊。這甚至包括在開始或結束時重疊一天。

+1

使用* SUM *而不是* LAST_VALUE *的不錯而優雅的方法。但我認爲在子問題中的條件應該是'where t2.end> t.start和t2.start = t.start和t2.start <= t.end' 。 1)只有開始日用於測試重疊,即只考慮左側。 2)至少有一個條件應該*小於*。否則子查詢返回**總是**記錄。 –

+0

@MarmiteBomber。 。 。其實,改變不平等是行不通的。該表需要一個主鍵來防止統計相同的記錄。真的很好。 –

+0

謝謝@戈登,我接近填補SR * *意外行爲* :) –

1

更多棘手的任務,因爲你不能相信間隔的任何順序。 我通過刪除子區間(在其他區間完全覆蓋的區間)來攻擊它。 在此之後,我可以按照START_DATE定義的順序來查看感知間隔是否與下一個間隔重疊並應用標準分組機制。

with subs as (
/* first remove all intervals that are subsets of other intervals */ 
select * from tst t1 
where NOT exists (select null from tst t2 where t2.start_date < t1.start_date and t1.end_date < t2.end_date) 
),overlap as (
select APPLN_NO, START_DATE, END_DATE, 
case when (nvl(lag(END_DATE) over (partition by APPLN_NO order by START_DATE),START_DATE-1) < START_DATE) then 
     row_number() over (partition by APPLN_NO order by START_DATE) end grp 
from subs), 
overlap2 as (
select 
APPLN_NO, START_DATE, END_DATE, GRP, 
last_value(grp ignore nulls) over (partition by APPLN_NO order by START_DATE) as grp2 
from overlap) 
select 
    APPLN_NO, min(START_DATE) START_DATE, max(END_DATE) END_DATE 
from overlap2 
group by APPLN_NO, grp2 
order by 1,2 
; 

對於這裏檢查查詢我的設置

drop table tst ; 
create table tst 
(appln_no number, 
start_date date, 
end_date date); 

insert into tst values (1001009, to_date('01-10-15','dd-mm-rr'),to_date('06-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('02-10-15','dd-mm-rr'),to_date('04-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('03-10-15','dd-mm-rr'),to_date('04-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('03-10-15','dd-mm-rr'),to_date('05-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('04-10-15','dd-mm-rr'),to_date('07-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('09-10-15','dd-mm-rr'),to_date('10-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('12-10-15','dd-mm-rr'),to_date('16-10-15','dd-mm-rr')); 
insert into tst values (1001009, to_date('13-10-15','dd-mm-rr'),to_date('14-10-15','dd-mm-rr')); /* this is added to make it more interesting */ 
insert into tst values (1001009, to_date('15-10-15','dd-mm-rr'),to_date('17-10-15','dd-mm-rr')); 

APPLN_NO START_DATE   END_DATE   
---------- ------------------- ------------------- 
    1001009 01.10.2015 00:00:00 07.10.2015 00:00:00 
    1001009 09.10.2015 00:00:00 10.10.2015 00:00:00 
    1001009 12.10.2015 00:00:00 17.10.2015 00:00:00 

預期。

+0

非常感謝。我回到辦公室後我會檢查這個。但我有一個疑問。此查詢將在oracle sql developer中正常工作,對嗎?到目前爲止,我還沒有在任何oracle查詢中使用'with subs as'。 – Mathew

+0

@Mathew不要wory [subquery保理](http://docs.oracle.com/cd/B19306_01/server。102/b14200/statements_10002.htm#i2129904)在Sql Developer中工作就像一個魅力。 –