2012-09-17 29 views
3

(PostgreSQL 8.4)我對SQL間隙和島嶼進行了很好的介紹here on Stack Overflow但我仍然有一個問題。許多島嶼檢測CTE基於時間戳的運行順序和一些標誌,當它改變時會中斷順序。但是如果「休息」情況稍微複雜一點呢?在多個參數和條件下檢測SQL島

CREATE TABLE T1 
(
    id SERIAL PRIMARY KEY, 
    val INT, -- some device 
    status INT -- 0=OFF, 1=ON 
); 

INSERT INTO T1 (val, status) VALUES (10, 1); 
INSERT INTO T1 (val, status) VALUES (10, 0); 
INSERT INTO T1 (val, status) VALUES (11, 1); 
INSERT INTO T1 (val, status) VALUES (11, 1); 
INSERT INTO T1 (val, status) VALUES (10, 0); 
INSERT INTO T1 (val, status) VALUES (12, 1); 
INSERT INTO T1 (val, status) VALUES (13, 1); 
INSERT INTO T1 (val, status) VALUES (13, 0); 
INSERT INTO T1 (val, status) VALUES (13, 1); 

在這種情況下,val表示的裝置,並且status要麼ONOFF。我想用以下邏輯選擇記錄1,3,6,79

  1. 10接通 - OK,新的序列,包括在SELECT

  2. 10熄滅 - 正常結束序列,忽略行

  3. 11接通 - OK,新的序列,包括在SELECT

  4. 11接通 - 複製,忽略行

  5. 10熄滅 - #10是不是ON,忽視

  6. 12變爲ON - 確定,隱式斷開#11,包括在SELECT

  7. 13變爲ON - 確定,隱式斷開#12,包括在SELECT

  8. 13斷開 - 結束序列正確,忽略行

  9. 13開啓 - OK,新的序列,包括在SELECT

Basicall Y,只有一個設備可以在一個時間是ON,而 「打破」 的條件是:

  • new.val = running.val AND new.status = 0
  • new.val <>運行。 VAL和new.status = 1

我正在尋找在CTE的形式的東西,不光標請

+0

給你想要的行,即第一個條件就是噪音。你根本不會對'OFF'行感興趣。 –

+0

增加了兩個額外的行(8,9)以及解釋。 – Jeff

回答

2

回答更新問題

SELECT * 
FROM (
    SELECT * 
     ,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val 
     ,lag(status) OVER (PARTITION BY val ORDER BY id) last_status 
    FROM t1 
    ) x 
WHERE status = 1 
AND (last_val <> val OR last_status = 0) 

如何?

和以前一樣,但是這次結合了兩個窗口函數。開啓設備符合條件如果..
1.最後打開的設備是不同的之一。
2.或相同的設備已在其最後一個條目中被切換關閉。與NULL爲第一行分區的角落案例是無關緊要的,因爲那麼行已經在1合格。


回答問題的原始版本。

如果我正確地理解你的任務,這個簡單的查詢這項工作:

SELECT * 
FROM (
    SELECT * 
     ,lag(val, 1, 0) OVER (ORDER BY id) last_on 
    FROM t1 
    WHERE status = 1 
    ) x 
WHERE last_on <> val 

返回行1,3,6,如要求7。

怎麼樣?

根據您的描述,子查詢忽略所有關閉,因爲這只是噪聲。設備開啓時留下條目。其中只有那些條目被取消資格,其中已經有相同的設備(最後一個條目開啓)。爲此,請使用window function lag()。特別是我提供0作爲默認值來覆蓋第一行的特殊情況 - 假設沒有val = 0的設備。
如果有,請選擇另一個不可能的數字。
如果沒有數字是不可能的,離開的特殊情況下,NULLlag(val) OVER ...並與外部查詢檢查:

WHERE last_on IS DISTINCT FROM val 
+0

這確實很好,但我錯過了一個例子來說明爲什麼我認爲地位很重要。考慮額外的兩行,從13開始增加一個OFF,然後再增加一個ON。連續兩次相同的設備,忽略滯後(需要拾取第9行) – Jeff

+0

@Jeff:我添加了另一個解決方案。僅供參考,如果您對您的問題有更新,將會使現有答案失效,建議您的方式是*開始一個新問題*。我們可能會回滾此類修改。我一次添加了一個新的答案。 –

+0

理解 - 並感謝您的幫助。 – Jeff