SQL - 设置差异并获取不属于差异的字段

时间:2011-05-05 19:47:35

标签: sql oracle set-difference

我有一个基本上执行如下操作的查询:

select a, b, c
from tab
where tab.state = 'A'
minus
select a, b, c
from tab
where tab.state = 'B'

在此示例中,abc是此表的关键字段。 state也是密钥的一部分,我正在尝试找到状态A中有记录而不是状态B的情况。还有另一个字段(不在密钥中)我想要报告value,对于不同州的相同记录可能有所不同。例如:

a  b  c  state  value
---------------------
1  1  1  A      12
1  2  2  A      1002
1  3  9  A      43
1  1  1  B      17.34
1  2  2  B      1002

在这种情况下,我对其键为1,3,9的行感兴趣,其中state为A.我还想获取value列的值,但是如果我尝试:

select a, b, c, value
from tab
where tab.state = 'A'
minus
select a, b, c, value
from tab
where tab.state = 'B'

我得到的是两行:

a  b  c    value
----------------
1  1  1      12
1  3  9      43

基本上,我希望结果集中包含value,但不参与minus。我觉得我在这里遗漏了一些明显的东西,但也许我太累了,无法得到它......;)

3 个答案:

答案 0 :(得分:3)

这样做的显而易见的方法是:

select a, b, c, value
from tab
where tab.state = 'A' and not exists (
  select 1                          -- let the optimizer do its thing
  from tab ti
  where tab.state = 'B' and ti.a=tab.a and ti.b=tab.b and ti.c=tab.c)

如果数据可以有双打,我甚至会在外部查询中添加distinct

答案 1 :(得分:1)

您可以将state = 'A'state = 'B' ...

匹配的所有行合并到一起
SELECT t1.a, t1.b, t1.c, t1.value, t2.value v2
FROM (SELECT a, b, c, value FROM tab WHERE state = 'A') t1
     LEFT JOIN (SELECT a, b, c, value FROM tab WHERE state = 'B') t2
            ON t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c

...然后选择没有匹配的行:

 SELECT a, b, c, value
 FROM ( /* previous query */ )
 WHERE v2 IS NULL

答案 2 :(得分:0)

SELECT a,
  b,
  c,
  value
FROM tab tab1
INNER JOIN
  (SELECT a, b, c FROM tab WHERE tab.state = 'A'
  MINUS
  SELECT a, b, c FROM tab WHERE tab.state = 'B'
  ) tab2
ON tab1.a  = tab2.a
AND tab1.b = tab2.b
AND tab1.c = tab2.c 

我相信上面的代码可以解决问题。