2017-09-06 22 views
3

上下文: 我有一个选择查询,我有设备之间的链接。一些链接有“反向重复”,我想摆脱选择查询。如何从SQL查询中删除相反的副本

我已经搜索了类似的问题,尤其是这一个:Remove reverse duplicates from an SQL query

但解决方案在这里工作,因为它只有重复使用的命令,但它并不适用于我的情况。

下面是数据的例子查询更容易的小提琴测试

http://sqlfiddle.com/#!17/214e6/7

insert into link (ip_src, ip_dst) values ('192.168.0.1','192.168.0.2'); 
insert into link (ip_src, ip_dst) values ('192.168.0.1','192.168.0.3'); 
insert into link (ip_src, ip_dst) values ('192.168.0.5','192.168.0.4'); 
insert into link (ip_src, ip_dst) values ('192.168.0.7','192.168.0.8'); 
insert into link (ip_src, ip_dst) values ('192.168.0.8','192.168.0.7'); 

期望的结果:

'192.168.0.1', '192.168.0.2' 
'192.168.0.1', '192.168.0.3' 
'192.168.0.5', '192.168.0.4' 
'192.168.0.7', '192.168.0.8' 
+0

是否要从表中删除它们,或者只是在选择查询的结果中将其删除? – wildplasser

+0

@wildplasser我只是想从结果中获得灵感。从下面的答案中使用最少和最大的功能对我来说工作得很好。你有另一种选择吗? – kenfire

+0

有一个很好的机会,至少()和最大()是不可靠的。 – wildplasser

回答

1

如果你不关心排序在最终结果集中,您可以这样做:

select distinct least(ip_src, ip_dst) as ip_src, greatest(ip_src, ip_dst) as ip_dst 
from link ; 

注意:这可能导致配对不在原始表中。

如果你关心排序:

select ip_src, ip_dst 
from link l 
where ip_src <= ip_dst 
union all 
select ip_src, ip_dst 
from link l 
where ip_src > ip_dst and 
     not exists (select 1 from link l2 where l2.ip_src = l.ip_dst and l2.ip_dst = l.ip_src); 

注:本品采用union all,所以它不会删除重复。您可以使用union删除重复项。

0
SELECT * 
FROM link l 
WHERE NOT EXISTS (
     SELECT * from link nx 
           -- The condition below is true for both the twins 
     WHERE nx.ip_src = l.ip_dst AND nx.ip_dst = l.ip_src 
           -- this is true for only one of the twins 
     AND nx.ip_src < nx.ip_dst 
     );