2017-10-09 81 views
0

我想查询包含具有与其他行相反的值的行的数据库表。所以表看起来像这样使用反向/交换值抑制行

Src   Trgt   ValueA   ValueB  
A    B    1,44    5 
B    A    1,44    5 <-- 
C    D    1,23    8 
D    C    1,23    8 <-- 
F    G    5,12    9 
G    F    5,12    9 <-- 

我要的是一个返回与源和目标价值交换不再做所有行的查询。不应该被查询的行是与另一行具有相同的值A和B的行,但仅与源和目标值交换(上面标记的那些) 因此,期望的结果将如下所示:

Src   Trgt   ValueA   ValueB  
A    B    1,44    5 
C    D    1,23    8 
F    G    5,12    9 
+0

D/E发生了什么? –

+0

我的错,更新了桌子。谢谢 – Chris

回答

1

我想这是你想要什么:

select t.* 
from t 
where t.src < t.trgt 
union all 
select t.* 
from t 
where t.src > t.trgt and 
     not exists (select 1 
        from t t2 
        where t2.src = t.trgt and t2.trgt = t.src and 
         t2.a = t.a and t2.b = t.b 
       ); 

它使遇到的第一行,过滤掉其中的前两列交换等价行。

编辑:

,如果你只是一个接一个,每个连击行是另一种方法:

select least(src, trgt) as src, greatest(src, trgt) as trgt, a, b 
from t 
group by least(src, trgt), greatest(src, trgt), a, b; 

这将运行在原始数据不返回行的风险(如果行有没有重复的和trgt > src

+0

没有工会没有办法做到这一点?如果表t会被广泛的子查询切换,我认为事情会很慢。 – Chris

+0

首先选择将忽略src = trgt(替换<= <= ???)的记录,在“exists”之前插入缺少的“not”,Second select将不起作用,因为a和b未包含在某个聚合函数中!也许可以用窗口函数重写。 –

+0

@ChristophG。 。 。当src和target相等时,OP没有声明该怎么做。 –

1
SELECT * 
FROM ztable zt 
WHERE zt.source < zt.target -- pick only one of the twins 
OR NOT EXISTS(    -- OR :if it is NOT part of a twin 
     SELECT * 
     FROM ztable nx 
     WHERE nx.source = zt.target 
     AND nx.target = zt.source 
     ); 

假设与source=target AR行不存在或不需要。