简体   繁体   English

MINUS vs NOT in where子句

[英]MINUS vs NOT in where clause

I have a query which retrieves data from a single table. 我有一个查询从一个表中检索数据。 However the query uses the MINUS clause like this: 但是查询使用MINUS子句,如下所示:

SELECT field1, field2
FROM tab
WHERE field3 = 'a'
AND field4 = 'b'
    MINUS
SELECT field1, field2
FROM tab
WHERE field5 = 'c'
AND field6 = 'd'

Since this is selecting from the same table I am trying to rewrite this to get rid of the MINUS clause. 由于这是从同一个表中选择,我试图重写它以摆脱MINUS子句。 I thought that something like this should work: 我认为这样的事情应该有效:

SELECT DISTINCT field1, field2
FROM tab
WHERE field3 = 'a'
AND field4 = 'b'
AND NOT (field5 = 'c'
AND field6 = 'd')

My reasoning is that if the MINUS clause excludes records in the second query, then wrapping the WHERE clause in an AND NOT should get rid of the same records. 我的理由是,如果MINUS子句排除第二个查询中的记录,那么将WHERE子句包装在AND NOT应该去掉相同的记录。 The MINUS clause also gets rid of duplicates which is why I added DISTINCT to the selection. MINUS子句也删除了重复,这就是我将DISTINCT添加到选择中的原因。 However the problem is that my query is returning more records than the original. 然而,问题是,我查询比原来更加返回的记录。

What am I missing here? 我在这里错过了什么?

Consider these two rows: 考虑这两行:

1, 2, a, b, x, y 1,2,a,b,x,y

1, 2, u, v, c, d 1,2,u,v,c,d

The MINUS operation will not return the pair (1, 2) but your query will. MINUS操作不会返回对(1,2),但您的查询将会。 The c, d values may appear with the same 1, 2 but in a different row from the a, b c,d值可能与1,2相同,但与a,b的行不同

The fundamental distinction is that MINUS operates at the set level, while your NOT condition only works on one row at a time (the same row with the "required" values in the other columns). 根本区别在于MINUS在设定级别运行,而NOT条件一次只能在一行上运行(在其他列中具有“必需”值的同一行)。

Now: You CAN make your query a bit more efficient (although you can't avoid reading the base table twice). 现在:您可以使您的查询更有效(尽管您无法避免两次读取基表)。 Use a NOT IN condition: 使用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');

Note (see spencer7593's comment below): As in all cases when NULLs may be present, NOT IN is not a good solution. 注意 (请参阅下面的spencer7593注释):在所有可能存在NULL的情况下,NOT IN不是一个好的解决方案。 Rather, a NOT EXISTS condition should be used. 相反,应该使用NOT EXISTS条件。 I won't elaborate, since it seems out of scope for the question asked (which was why the "NOT" solution is different from the "MINUS" solution). 我不会详细说明,因为它似乎超出了所提问题的范围(这就是“NOT”解决方案与“MINUS”解决方案不同的原因)。

In this solutions the table is being referenced only once. 在此解决方案中,该表仅被引用一次。

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
;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM