2010-03-22 115 views
3

我有一個包含一些名字及其相關ID的表,其中的快照一起:檢測變化

snapshot, systemid, name[, some, other, columns] 

我需要找出所有的獨特name s表示一個systemid已經遍及所有有快照,但只有至少有一次更改。

例如,與數據:

'DR1', 0, 'MOUSE_SPEED' 
'DR1', 1, 'MOUSE_POS' 
'DV8', 0, 'MOUSE_BUTTONS' 
'DV8', 1, 'MOUSE_POS' 
'DR6', 0, 'MOUSE_BUTTONS' 
'DR6', 1, 'MOUSE_POS' 
'PP2', 0, 'MOUSE_SPEED' 
'PP2', 1, 'MOUSE_POS' 

...我想要一個查詢,將返回(以任意順序):

0, 'MOUSE_SPEED' 
0, 'MOUSE_BUTTONS' 

此外,這將是有益的反過來 - systemid s的列表在全部snapshot s(也就是說,name從未改變過)中保持穩定。

我正在使用PostgreSQL v8.4.2。

編輯:更新,以反映的意見(對不起,原低於完美的帖子,我是新來的!)

+2

如果它在快照3中發生更改,您會列出什麼? – Unreason 2010-03-22 15:55:41

+2

如果無法對快照值進行排序(直接或通過其他字段),則無法從樣本數據中區分2,0,'MOUSE_BUTTONS'和3,0'MOUSE_BUTTONS'。 你關心哪一個被選中?如果是的話,你是如何選擇它作爲結果的例子? – Unreason 2010-03-22 16:59:54

+0

我建議你爲我們提供真實的數據。我們不介意幫忙,但是留下太多的猜測或提供錯誤的意見只會浪費您和我們的時間。考慮到你是新的,所以我確信每個人都能理解,但對於將來的問題,這是一個很好的建議。 – 2010-03-22 17:51:04

回答

0

以下是SQL Server,但它不使用任何SQL Server特定的結構。它應該是可移植的postgresql。

SQL語句

SELECT DISTINCT t1.id, t1.name 
FROM @Table t1 
     INNER JOIN (
      SELECT t.id 
      FROM (
        SELECT DISTINCT id, name 
        FROM @Table 
       ) t 
      GROUP BY t.id 
      HAVING COUNT(*) > 1 
     ) t2 ON t2.id = t1.id 

測試數據

DECLARE @Table TABLE (snapshot INTEGER, id INTEGER, name VARCHAR(32)) 

INSERT INTO @TABLE 
SELECT 1, 0, 'MOUSE_SPEED' 
UNION ALL SELECT 1, 1, 'MOUSE_POS' 
UNION ALL SELECT 1, 2, 'KEYBOARD_STATE' 
UNION ALL SELECT 2, 0, 'MOUSE_BUTTONS' 
UNION ALL SELECT 2, 1, 'MOUSE_POS' 
UNION ALL SELECT 2, 2, 'KEYBOARD_STATE' 
UNION ALL SELECT 3, 0, 'MOUSE_SPEED' 
UNION ALL SELECT 3, 1, 'MOUSE_POS' 
UNION ALL SELECT 3, 2, 'KEYBOARD_STATE' 
+0

對不起,快照字段是一個字符串,例如'PP16','PP16B','DS21'。沒有保證它們的順序 - 我不介意修改了哪些順序,只是修改順序和修改快照。 – Noah 2010-03-22 16:36:58

+1

@Noah,如果您無法從其值中建立快照的順序,則無法建立其更改的快照順序。例如,如果PP16是MOUSE_POS,PP16B是MOUSE_POS,而DS21是MOUSE_BUTTONS,那麼你不能斷定它改變了哪一個。我可以聲稱它從MOUSE_POS更改爲MOUSE_BUTTONS回到MOUSE_POS,但同樣我可以聲稱它以MOUSE_POS開始,保持原狀並更改爲MOUSE_BUTTONS(存在其他組合)。 – Unreason 2010-03-22 16:45:51

+0

@Noah:我已更新查詢以匹配您最近的修改。 – 2010-03-23 08:20:17

0

PostgreSQL有EXCEPT運算符,我記得它與MINUS(例如在Oracle中)幾乎相同,所以也許類似的工作?

select id, name 
from some_table 
where snapshot = '1' and id in ('1', '2', '0') 
except 
select id, name 
from some_table 
where snapshot = '2' and id in ('1', '2', '0') 

如果您有多個shapshots,你可以嘗試他們都串聯成EXCEPT■一個長序列,或者你可以寫一個程序,反覆處理它們,如(僞):

for i = 1 to maX(snapshot)-1 loop 
    results := diff_query(i, i+1) //the query above, but inside a procedure or something 
    forall records in results loop 
     /* do your processing here */ 
    end loop 
end loop 

這看起來好像是使用集合運算符的那種東西。

0
select distinct s1.snapshot, s1.id, s1.name from snapshot s1, snapshot s2 
where s1.snapshot != s2.snapshot 
and s1.id = s2.id 
and s1.name != s2.name 
+0

已更新的SQL語句。 – geffchang 2010-03-22 16:11:28

+0

對不起,在示例中我沒有列出其他一些列(我不關心它們),所以DISTINCT不會將它們濾除。 – Noah 2010-03-22 16:13:45

0

對於那些改變:

SELECT t1.snapshot, t1.systemid 
FROM table t1 
GROUP BY t1.snapshot, t1.systemid 
HAVING min(t1.name) <> max(t1.name) 

會給你已經改變

對於保持不變

SELECT t1.snapshot, t1.systemid 
FROM table t1 
GROUP BY t1.snapshot, t1.systemid 
HAVING min(t1.name) = max(t1.name) 

聯袂值回到第一個或最後一個查詢的人的那些快照和id可以加入子查詢完成或相關子查詢

加入(例如用名稱,改變)

SELECT t2.snapshot, t2.systemid, t2.name 
FROM table t2 
    JOIN (
      SELECT snapshot, systemid 
      FROM table 
      GROUP BY snapshot, systemid 
      HAVING min(name) <> max(name)) t1 
    ON t2.snapshot = t1.snapshot AND t2.systemid = t1.systemid 

相關(例如與該名稱保持不變)

SELECT t2.snapshot, t2.systemid, t2.name 
FROM table t2 
WHERE t2.name IN (
      SELECT t1.name 
      FROM table t1 
      WHERE t2.snapshot = t1.snapshot AND t2.systemid = t1.systemid 
      GROUP BY t1.name 
      HAVING COUNT(DISTINCT t1.name) = 1) 

如果您不需要快照的反向查詢,然後

SELECT DISTINCT t2.systemid, t2.name 

和休息一樣。

查詢未驗證,但我希望方法很明確