我有一个包含一些名称及其相关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。
编辑: 已更新以反映评论(对于原始不太完美的帖子感到抱歉,我是新来的!)。
答案 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
并保持不变。
查询未经过验证,但我希望方法是明确的