我有以下MySQL表:
id rid
----- ------
1 2
2 1
2 3
3 2
1 3
3 1
我想更改此设置,以便每个关系仅存在一行。
例如:
id rid
----- ------
1 2
2 3
1 3
最佳答案
如果您总是成对出现(例如您的示例):
delete from table
where id > rid;
这样会保留
id
较小的记录。如果存在所有对都不存在的可能性,则:
delete t
from table t left outer join
(select least(id, rid) as lid, greatest(id, rid) as gid, count(*) as cnt
from table t2
group by least(id, rid), greatest(id, rid)
) t2
on least(t.id, t.rid) = t2.lid and greatest(t.id, t.rid) = gid
where id < rid or t2.cnt = 1;
编辑(解释):
第二个查询如何工作?老实说,我要写的是这样的:
delete t from table t
where id < rid or
(id > rid and
not exists (select 1 from table t2 where t2.id = t.rid and t2.rid = t.id
);
也就是说,我要将所有记录保留在
id < rid
所在的位置。但是然后,我也想将所有单例记录保留在rid > id
位置。我认为MySQL不允许where
子句使用语法。相反,答案中的查询通过查看最小值和最大值来计算一对存在的次数。对于问题中的数据,子查询的结果为:
id rid cnt
1 2 2
2 3 2
1 3 2
因此,所有这些都将使用
id < rid
选择该行。如果还有一行,请说4, 1
。它看起来像:lid gid cnt
1 2 2
2 3 2
1 3 2
1 4 1
在这种情况下,前三个将使用
id < rid
作为行。但是也会选择新行,因为cnt
为1。如果您在表和主键中有重复项,那么在查询上会做些相同的事情而稍有不同。
关于mysql - 删除交叉引用数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21353794/