2008-09-22 34 views
0

我有一個數據庫問題,我目前無法用簡單的解決方案來包裝我的頭。在我的分貝,我有一個表,存儲事件值.. 0和1與時間戳。問題在於,可能會有相同的事件發生兩次作爲業務規則。像下面在運行時在sql數據庫中過濾出重複值 - 基於

  • '2008-09-22 16:28:14.133',0
  • '2008-09-22 16:28:35.233',1
  • 「2008-09-22 16: 29:16.353' ,1
  • '2008-09-22 16:31:37.273',0
  • '2008-09-22 16:35:43.134',0
  • 「2008-09-22 16 :36:39.633',1
  • '2008-09-22 16:41:40.733',0

在現實生活中,這些事件是循環的,我試圖查詢以獲取這些循環,但我需要忽略重複值(1,1)當前的解決方案是使用SQL遊標來循環每個並拋出如果以前是相同的,那麼價值就會變大。我已經考慮過使用插入的觸發器來清理後處理表,但我想不出一個簡單的解決方案來做這個基於。

任何想法或建議嗎?

感謝

+0

你怎麼知道哪些是重複的值?你在桌子上有幾種主鍵? 現在我不知道如何分辨哪兩個記錄是相互關聯的。 – HLGEM 2008-09-22 20:52:28

回答

0

這將使用SQL Server的公共表表達式,但它可以被內聯,用表筆與DT列和cyclestate:

;WITH Firsts AS (
    SELECT t1.dt 
     ,MIN(t2.dt) AS Prevdt 
    FROM t AS t1 
    INNER JOIN t AS t2 
     ON t1.dt < t2.dt 
     AND t2.cyclestate <> t1.cyclestate 
    GROUP BY t1.dt 
) 
SELECT MIN(t1.dt) AS dt_start 
    ,t2.dt AS dt_end 
FROM t AS t1 
INNER JOIN Firsts 
    ON t1.dt = Firsts.dt 
INNER JOIN t AS t2 
    ON t2.dt = Firsts.Prevdt 
    AND t1.cyclestate <> t2.cyclestate 
GROUP BY t2.dt 
    ,t2.cyclestate 
HAVING MIN(t1.cyclestate) = 0 
1

(前言.......我只在Oracle這樣做,但我敢肯定,如果該數據庫支持觸發這一切都可能)

插入之前有一個觸發器,用於選擇具有最大時間戳值的行。如果該行的值與您希望插入的值相同,請忽略它。

這應該讓他們都處於正確的狀態。

現在,如果需要同時存儲兩組狀態,觸發器可以始終插入到全包式表中,但只有在值發生更改時才執行查找並插入「已過濾」表。

0

只是爲了讓我明白這個問題。

你,如果你基於時間戳命令行集,有時複製下一個值存在的彼此,就像在第2和第3RT項以上對1分的嗎?然後你在第四和第五位加倍0,是嗎?

而你想要對應的最後一個(或序列如果有超過2)?

爲什麼你需要刪除它們?我在問,因爲除非他們佔據了這張表的大小,否則當你需要處理或顯示它們時,可能更容易將它們過濾出來,就像順序進行過濾一樣。

一個解決方案,但沒有一個很好的一個,將檢索最小時間戳上述您正在檢查當前行的時間戳,然後檢索該值,如果是相同的,不要不會返回當前行。

這裏的SQL得到的一切:

SELECT timestamp, value 
FROM yourtable 

下面是如何加入到獲得當前的一個高於最低時間戳:

SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value 
FROM yourtable T1, yourtable T2 
WHERE T2.timestamp > T1.timestamp 
GROUP BY T1.timestamp, T1.value 

(我擔心上面的查詢將是可怕的慢)

然後檢索對應於該最小時間戳的值

SELECT T3.timestamp, T3.value 
FROM (
    SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value 
    FROM yourtable T1, yourtable T2 
    WHERE T2.timestamp > T1.timestamp 
    GROUP BY T1.timestamp, T1.value 
) T3, yourtable AS T4 
WHERE T3.next_timestamp = T4.timestamp 
    AND T3.value <> T4.value 

不幸的是,這不會產生最後一個值,因爲它需要一個下面的值來比較。一個簡單的虛擬哨兵價值(你可以在需要的情況下聯合)來處理這個問題。

下面是我測試上面的查詢對SQLite數據庫轉儲:

BEGIN TRANSACTION; 
CREATE TABLE yourtable (timestamp datetime, value int); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:28:14.133',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:28:35.233',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:29:16.353',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:31:37.273',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:35:43.134',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:36:39.633',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:41:40.733',0); 
INSERT INTO "yourtable" VALUES('2099-12-31 23:59:59.999',2); 
COMMIT; 

這裏是(格式化)輸出:

timestamp     value 
2008-09-22 16:28:14.133 0 
2008-09-22 16:29:16.353 1 
2008-09-22 16:35:43.134 0 
2008-09-22 16:36:39.633 1 
2008-09-22 16:41:40.733 0 
0

這個問題確實是一個數據採集的問題。典型的數據庫引擎不是一個很好的選擇來解決它。一個簡單的預處理器應該檢測輸入數據集中的變化並僅存儲相關數據(時間戳等)。

一個簡單的解決方案是在數據庫環境中(例如在Oracle中)創建一個包,該包可以具有用於存儲最後輸入數據集的本地內存變量並消除不必要的數據庫訪問。

當然,您可以使用數據庫環境的所有功能來定義「輸入數據集中的更改」並存儲過濾的數據。所以它可能很容易或複雜,因爲你whish。