检测具有相同ID的行之间的更改

时间:2010-03-22 15:45:32

标签: sql database postgresql

我有一个包含一些名称及其相关ID的表,以及一个快照:

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

我需要识别name在所有快照中所拥有的所有唯一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之间保持稳定的snapshot列表会很有用(也就是name 1}}从未改变过。)

我正在使用PostgreSQL v8.4.2。

编辑: 已更新以反映评论(对于原始不太完美的帖子感到抱歉,我是新来的!)

4 个答案:

答案 0 :(得分: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

这似乎是使用set运算符的那种东西。

答案 1 :(得分: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'

答案 2 :(得分: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

答案 3 :(得分:0)

对于改变的:

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

会为您提供已更改的快照和ID

对于那些保持不变的

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

将值连接回第一个或最后一个查询可以使用连接的子查询或相关子查询来完成

已加入(已更改名称的示例)

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

并保持不变。

查询未经过验证,但我希望方法是明确的