2017-02-01 11 views
1

考慮一個表,隨時跟蹤最喜歡的顏色。清除重疊從 - 有效到有效到

drop table favourites; 

create table favourites(
    person_id varchar2(10) not null 
    ,valid_from date   not null 
    ,valid_to date 
    ,color  varchar2(10) not null 
    ,constraint favourites_pk primary key(person_id, valid_from) 
); 

insert into favourites values('Ronnie', date '1979-09-12', null,    'Green'); 
insert into favourites values('Ronnie', date '2000-01-01', date '2016-12-31', 'Blue'); 

commit; 

該表指出''Ronnie'在1979-09-12喜歡綠色,然後從2000-01-01喜歡藍色。當Ronnie在2017年的第一天醒來時,他不再喜歡藍色。

我需要用一次性腳本清理表格,但是我被困在上面顯示的特定情況。到目前爲止最好的想法是根據valid_from日期重新計算valid_to日期,但在這種情況下,我實際上是在銷燬信息:如下所示,「綠色」不再是2017-01-01的最愛,它應該是。

select person_id 
     ,valid_from  
     ,valid_to 
     ,lead(valid_from,1) over(partition by person_id order by valid_from)-1 as valid_to2 
     ,color   
    from favourites t; 


PERSON_ID VALID_FROM VALID_TO NEW_VALID_TO COLOR 
--------- ---------- ---------- ------------ ------ 
Ronnie  1979-09-12 null  1999-12-31  Green 
Ronnie  2000-01-01 2016-12-31 null   Blue 

我怎麼能生成一個aditional的記錄,這樣,最終的結果將是:

PERSON_ID VALID_FROM VALID_TO COLOR 
--------- ---------- ---------- ------ 
Ronnie  1979-09-12 1999-12-31 Green 
Ronnie  2000-01-01 2016-12-31 Blue 
Ronnie  2017-01-01 null  Green 

編輯 有背後的valid_to日期沒有合理的邏輯。這是用戶輸入的內容,因此存在各種瘋狂的重疊。 null表示「永遠」,如果它更容易理解,則表示9999-12-31。我想通過創建另一個表來修復此設計,但首先我需要一種方法來修復舊數據。

也許這樣更容易看。

Green |----------------------------------> 
Blue   |------| 

我修復通過計算一個新的失效日期的日期的重疊,我破壞信息:

Green |--------| 
Blue   |------| 

它有被固定這樣的:

Green |--------| 
Blue   |------| 
Green     |--------> 

在原始數據集中的問題僅爲第二個查詢顯示(由於重疊)。另外兩個顯示正確的結果。

select * 
    from favourites 
where (date '1995-01-01' >= valid_from) 
    and (date '1995-01-01' <= valid_to or valid_to is null); 

select * 
    from favourites 
where (date '2015-01-01' >= valid_from) 
    and (date '2015-01-01' <= valid_to or valid_to is null); 

select * 
    from favourites 
where (date '2025-01-01' >= valid_from) 
    and (date '2025-01-01' <= valid_to or valid_to is null); 
+0

這是重疊的唯一的例子? –

+1

爲什麼新插入的行上的顏色應該是綠色的?它可以爲空嗎? –

+0

你怎麼知道他在2017年開始喜歡綠色?是否有某個默認規則? – tbone

回答

0

如果你的例子是,你所關心的一個類型重疊的,那麼你就可以union all處理這個問題。我想這是你想要的查詢:

select person_id, color, valid_from, 
     coalesce(valid_to, lead(valid_from) over (partition by person_id order by valid_from)-1) as valid_to2 
from favourites t 
union all 
select person_id, color, valid_to + 1 as valid_from, NULL as valid_to 
from favourites f 
where valid_from is null and 
     exists (select 1 from favourites f2 where f2.person_id = f.person_id and f2.valid_from > f.valid_from); 

通過唯一的類型,我的意思是,只有一個valid_fromNULL和記錄不重疊,否則。如果你有更多的生成問題,那麼你應該用適當的數據和解釋如何處理重疊問題來提出另一個問題。

0

獲取當前行的結束日期很簡單(從下一行的date_from減去1天)。但是,您應該生成一個需要union all的新行。另外,默認顏色被選擇爲valid_tonull的那行。 (如果不是這種情況,則需要更改cte中的邏輯)。

WITH CTE AS 
(SELECT PERSON_ID, 
     COLOR, 
     VALID_FROM, 
     ROW_NUMBER() OVER(PARTITION BY PERSON_ID ORDER BY VALID_FROM DESC) AS RNUM, 
     COALESCE(VALID_TO, LEAD(VALID_FROM) OVER (PARTITION BY PERSON_ID 
                ORDER BY VALID_FROM)-1) AS VALID_TO_NEW, 
     MAX(CASE WHEN VALID_TO IS NULL THEN COLOR END) 
        OVER(PARTITION BY PERSON_ID ORDER BY VALID_FROM) AS DEFAULT_COLOR 
    FROM FAVOURITES) 
SELECT PERSON_ID, 
     VALID_FROM, 
     VALID_TO_NEW, 
     COLOR 
FROM CTE 
UNION ALL 
--Generates a new last row with the default color if it exists 
SELECT PERSON_ID, 
     VALID_TO_NEW+1, 
     NULL, 
     DEFAULT_COLOR 
FROM CTE 
WHERE RNUM=1 

Sample Demo