Oracle MINUS两种方式(选择之间有区别)

时间:2017-06-22 14:34:20

标签: sql oracle

我想找到两个select语句中的所有行,其中行属于(所有列匹配) 选择语句但不是

我知道如何在单一方向实现这一目标

  select foo from foobar where bar = 1
minus
  select foo from foobar where bar = 2;

这将返回第一个选择语句中foo存在的所有行,但不返回最后一个,但不是其他方式。

我知道我能做到

    (select foo from foobar where bar = 1
  minus
    select foo from foobar where bar = 2)
union
    (select foo from foobar where bar = 2
  minus
    select foo from foobar where bar = 1);

返回所需的结果。但这是很多重复。是否有一些像minus这样的运算符可以同时运行?

另外,我想在结果中添加标识符,表示它属于哪个选择。但仅此一点就会使所有行都不同。

3 个答案:

答案 0 :(得分:1)

SET运算符仅

  

UNION由查询

选择的所有不同行      

UNION ALL由任一查询选择的所有行,包括所有行   重复

     

INTERSECT两个查询选择的所有不同行

     

MINUS由第一个查询选择但不是第二个

选择的所有不同行

你可以使用交叉但是选择的数量是非常相同的

  (select foo from foobar where bar = 1
  union 
  select foo from foobar where bar = 2)
  minus 
  (select foo from foobar where bar = 1
  intesect
  select foo from foobar where bar = 2)

答案 1 :(得分:1)

如果两个行集(无论是基表还是其他计算结果)已经重复数据删除,那么您可以使用

select foo
from (
       select foo from rowset_1
       union all
       select foo from rowset_2
     )
group by foo
having count(*) = 1

优点 - 特别是如果行集是基表 - 是每个只扫描一次,而不是每次扫描两次。

如果结果集未进行重复数据删除,您可以在两个地方select foo更改select distinct foo

如果您可能在每个结果集中都有重复项,并且您还希望显示两个表共有的行(foo值),但具有不同的多重性(例如,三个重复项),则会有类似的解决方案一行,但另一行有五个重复。)

答案 2 :(得分:1)

在这种情况下(总是相同的表),您可以简单地聚合:

select foo, max(bar)
from foobar 
where bar in (1,2)
group by foo
having count(distinct bar) = 1;

这给你所有foo只有bar 1或bar 2而不是两者。 max(bar)告诉你foo有两个值中的哪一个。