2017-09-15 79 views
2

下面是我的SQL代码:为什么SQL“NOT IN”太慢?

select count(1) 
from customers 
where id in(
    select custid 
    from accounts 
    where sid in(72,73,74,75,76,77,78,79) 
) 
and id not in(
    select custid 
    from accounts 
    where sid in(80,81) 
); 

表都编入索引。此代码是否可以重写以获得更好的性能?

+1

请** [编辑] **您的问题,并添加所涉及的表(包括所有索引),您正在使用的查询和生成的执行计划的'create table'语句**解释(分析,详细)**。 [**格式化文本**](http://stackoverflow.com/help/formatting)请(请确保您保留缩进),[无屏幕截图](http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-code-on-so-when-asked-question/285557#285557) –

+1

可以在不改变结果的情况下移除NOT IN标准。请回顾一下您的问题。 –

+1

@PatrickHonorez - 我读到它的方式,给定的id可能在帐户表中有多行。如果该表中的id同时具有sid = 72和sid = 80的情况,则不应该计数,因此需要NOT IN – kbball

回答

3

您也可以尝试存在:

select count(1) 
from customers c 
where exists (
    select 1 
    from accounts a 
    where sid in(72,73,74,75,76,77,78,79) 
    and a.custid = c.custid 
) 
and not exists (
    select 1 
    from accounts a 
    where sid in(80,81) 
    and a.custid = c.custid 
); 

这可能是有益的读取:Difference between EXISTS and IN in SQL?

+0

WOW!将无法给出正确的结果!我已经在一秒钟而不是5分钟的结果! – user3260061

0

加入您的表格而不是使用2个子语句。

SELECT count(1) 
FROM customers c 
INNER JOIN accounts a ON c.id = a.sid 
WHERE id IN (72, 73, 74, 75, 76, 77, 78, 79) 
+0

计数过高,因为您可能会计算在帐户中有一行的id(80,81) – kbball

+2

如果客户拥有多个帐户 –

0

A减查询可能会更有效。就像这样:

SELECT count(1) 
FROM 
(
SELECT c.id 
FROM customers c 
INNER JOIN accounts a ON c.id = a.sid 
WHERE id IN (72, 73, 74, 75, 76, 77, 78, 79) 
MINUS 
SELECT c.id 
FROM customers c 
INNER JOIN accounts a ON c.id = a.sid 
WHERE id IN (80,81) 
) 
+1

我试过这个,但得到了一个语法错误 - 接近MINUS。 – user3260061