【问题标题】:Why SQL "NOT IN" is so slow?为什么 SQL “NOT IN” 这么慢?
【发布时间】:2018-02-24 15:57:32
【问题描述】:

下面是我的 SQL 代码:

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)
);

表格索引正确。能否重写此代码以获得更好的性能?

【问题讨论】:

  • Edit您的问题并为有问题的表(包括所有索引)添加create table语句,您正在使用的查询和使用生成的执行计划explain (analyze, verbose)Formatted text 请(确保保留缩进),no screen shots
  • NOT IN 条件可以被删除而不改变结果。请检查您的问题。
  • @PatrickHonorez - 按照我的阅读方式,给定的 id 可以在帐户表中有多行。如果该表中的 id 同时具有 sid = 72 和 sid = 80 的情况,则不应将其计算在内,因此需要 NOT IN
  • @kbball 知道了。有趣,很好,你澄清了它。

标签: sql postgresql


【解决方案1】:

你也可以试试 EXISTS:

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?

【讨论】:

  • 哇!我在一秒钟内而不是 5 分钟内得到结果!
【解决方案2】:

加入您的表,而不是使用 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)

【讨论】:

  • 计数会太高,因为您可能会计算在 sid in (80, 81) 的帐户中有一行的 ID
  • 如果客户有多个帐户,则不会给出正确的结果
【解决方案3】:

减号查询可能更有效。像这样的:

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)
)

【讨论】:

  • 我已经尝试过了,但出现语法错误 - 靠近 MINUS。
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 2011-05-26
  • 2012-04-30
  • 2014-03-12
  • 1970-01-01
  • 2020-11-25
  • 2021-09-03
  • 2017-10-26
相关资源
最近更新 更多