MINUS vs NOT in where子句

时间:2016-12-08 22:11:57

标签: sql database oracle

我有一个查询从一个表中检索数据。但是,查询使用for (auto it = map.begin(); it != map.end; ) { answer[it->first-1] = it->first * it->second; //take the derivative it = map.erase(it); } 子句,如下所示:

MINUS

由于这是从同一个表中选择,我试图重写它以摆脱SELECT field1, field2 FROM tab WHERE field3 = 'a' AND field4 = 'b' MINUS SELECT field1, field2 FROM tab WHERE field5 = 'c' AND field6 = 'd' 子句。我认为这样的事情应该有效:

MINUS

我的理由是,如果SELECT DISTINCT field1, field2 FROM tab WHERE field3 = 'a' AND field4 = 'b' AND NOT (field5 = 'c' AND field6 = 'd') 子句排除第二个查询中的记录,那么将MINUS子句包装在WHERE中应该删除相同的记录。 AND NOT子句也摆脱了重复,这就是我在选择中添加MINUS的原因。但问题是我的查询返回更多记录而不是原始记录。

我在这里缺少什么?

2 个答案:

答案 0 :(得分:5)

考虑这两行:

1,2,a,b,x,y

1,2,u,v,c,d

MINUS操作不会返回对(1,2),但您的查询将会。 c,d值可能出现相同的1,2,但与a,b

的行不同

根本区别在于MINUS在设定级别运行,而NOT条件一次只能在一行上运行(在其他列中具有“必需”值的同一行)。

现在:您可以使查询更有效(尽管您无法避免两次读取基表)。使用NOT IN条件:

select field1, field2 from tab where field3 = 'a' and field4 = 'b'
and    (field1, field2) not in 
           (select field1, field2 from tab where field5 = 'c' and field6 = 'd');

注意(参见下面的spencer7593评论):在所有可能存在NULL的情况下,NOT IN不是一个好的解决方案。相反,应该使用NOT EXISTS条件。我不会详细说明,因为它似乎超出了所提问题的范围(这就是为什么“NOT”解决方案与“MINUS”解决方案不同)。

答案 1 :(得分:2)

在此解决方案中,该表仅被引用一次。

select      field1,field2

from        tab

where       (field3,field4) in (('a','b'))
        or  (field5,field6) in (('c','d'))

group by    field1,field2

having      max(case when (field5,field6) in (('c','d')) then 1 else 0 end) = 0
;

OR

select      field1,field2

from        tab

group by    field1,field2

having      max(case when (field3,field4) in (('a','b')) then 1 else 0 end) = 1
        and max(case when (field5,field6) in (('c','d')) then 1 else 0 end) = 0
;