2012-09-10 49 views
0

我正在使用一個表格,每個ID都有一個「事件」列表,其中一個事件是否由該ID表示的對象變爲「開「或」關「。如果它們不在此表中,則假定項目從關閉開始。一件物品如果在那時尚未開啓,則只能依法繼續。Oracle SQL - 使用「不可能」日期範圍修復數據

下面是它可能看起來像一個例子:

Events 
ID Type Date 
1 On  01-MAY-12 
1 Off  01-JUN-12 
1 On  05-JUN-12 

不幸的是,這個數據是可怕的,它充滿了不可能的事。以下是該表的一部分,實際上是這樣的:

Events 
ID Type Date 
1 On  01-MAY-12 
1 On  01-MAY-12 
1 On  01-JUN-12 
1 Off  01-JUL-12 
1 Off  01-AUG-12 
1 On  05-AUG-12 

我想要做的就是寫一個返回該表中沒有垃圾數據,查詢在那裏不可能行(即,把該項目時,它的行已經打開,或已關閉時關閉)被刪除。

我並不在乎它在第一次被開啓之前「關閉」的情況,因爲我不相信我們有任何這種情況。

所以說,查詢將返回:

Events 
ID Type Date 
1 On  01-MAY-12 
1 Off  01-JUL-12 
1 On  01-AUG-12 

如何做到這一點有什麼想法?這種「在條件X下返回第一行」的邏輯給我帶來了很多困難。如果我只想要第一排或第一排,我可以分組,並抓住一分鐘。但在這種情況下我該如何做?

+0

我注意到''(ID,Date)'中有一些重複,至少在一天的粒度。在這種情況下,你如何決定哪個更老,哪個更新?他們有不同的小時/分鐘/秒嗎? – ruakh

+0

@ruakh我並不在乎,但在這種情況下,這是因爲粒度降到了秒,所以一個真正在另一個之前。 – Jeremy

回答

5

你可以這樣寫:

SELECT id, 
     type, 
     "date" 
    FROM (SELECT id, 
       LAG(type) OVER (PARTITION BY id ORDER BY "date") AS prev_type, 
       type, 
       "date" 
      FROM events 
     ) 
WHERE type <> NVL(prev_type, '-') 
ORDER 
    BY "date" 
; 

注意:除非你用雙引號把它包

  • date是不是真的有效的列名。我猜這不是專欄的名字?
  • 你寫道:「我沒有太在意第一次打開它之前關閉它的情況,因爲我不相信我們有任何這樣的情況」,所以我決定不要這樣做刪除初始Off s,但這實際上並不困難:只需將NVL(prev_type, '-')更改爲NVL(prev_type, 'Off')即可。
  • 我並不擔心你有兩個記錄與id"date"type不同,因爲我不知道你想如何處理。我希望你不需要把它們放在任何順序 - 使它們成爲可能,因爲那會更加困難。
+0

這絕對是不可思議的,也是比我想象的更好的解決方案。我也不熟悉滯後函數。我將能夠自己處理邊緣案例。謝謝。 – Jeremy

+0

@Jeremy:不客氣! – ruakh