【问题标题】:Efficient way to select all values from one column not in another column从一列而不是另一列中选择所有值的有效方法
【发布时间】:2012-02-02 22:58:31
【问题描述】:

我需要从colA 返回所有不在colB 中的值从mytable。我正在使用:

SELECT DISTINCT(colA) FROM mytable WHERE colA NOT IN (SELECT colB FROM mytable)

它正在运行,但是查询需要很长时间才能完成。

有没有更有效的方法来做到这一点?

【问题讨论】:

  • NOT IN 会随着集合大小的增加而变慢,并且NOT IN 子句中的行数通常会受到限制。在小的结果集之外,我发现使用其他方法来获得两个结果集之间的差异会更好。
  • 在谈到性能时,您必须为您的 RDBMS 命名或获得次优答案。

标签: sql performance distinct notin


【解决方案1】:

在标准 SQL 中,DISTINCT colA 中没有括号DISTINCT 不是函数。

SELECT DISTINCT colA
FROM   mytable
WHERE  colA NOT IN (SELECT DISTINCT colB FROM mytable);

也将DISTINCT 添加到子选择中。如果您有许多重复项,则可以加快查询速度。

CTE 可能会更快,具体取决于您的 DBMS。我还演示了LEFT JOIN 作为排除valB 中的值的替代方法,以及使用GROUP BY 获得不同值的替代方法:

WITH x AS (SELECT colB FROM mytable GROUP BY colB)
SELECT m.colA
FROM   mytable m
LEFT   JOIN x ON x.colB = m.colA
WHERE  x.colB IS NULL
GROUP  BY m.colA;

或者,进一步简化,并使用简单的子查询(可能最快):

SELECT DISTINCT m.colA
FROM   mytable m
LEFT   JOIN mytable x ON x.colB = m.colA
WHERE  x.colB IS NULL;

基本上有 4 种技术可以排除另一个(或同一个)表中存在键的行:

速度的决定因素将是索引。您需要在 colAcolB 上建立索引才能使此查询更快。

【讨论】:

  • 谢谢,我试过了:SELECT DISTINCT m1.colA FROM mytable m1 LEFT JOIN mytable m2 ON (m1.colA = m2.colB) WHERE m2.colA IS NULL ORDER BY m1.colA ASC,它的速度快了几个数量级,而且似乎工作正常 - 这是否等同于我在问题中发布的代码?它是如此之快,以至于我怀疑我可能错过了一些东西。
  • @Andrew:抱歉,您的查询中有错字。必须是WHERE m2.colB IS NULL。使用LEFT JOIN (SELECT DISTINCT colB FROM mytable) m2 ON m2.colB = m1.colA if (更正后的)查询可能会更快,colB 有许多重复值。
  • @Andrew: m2.colA 总是NULL 如果m2.colB 在这里是NULL,但m2.colA 可以是NULL,即使m2.colB 不是。所以这里正确(而且更快!)的形式是:WHERE m2.colB IS NULL如果 colA 被定义为NOT NULL,那么你上面的查询是正确的。
  • 谢谢,由于没有NULL 值,查询给了我相同数量的结果。你知道它为什么这么快吗?
  • @Andrew:不同的查询计划执行不同。如果不知道您使用的是哪个 RDBMS,我无话可说。您可能希望将该信息编辑到您的问题中。有关索引的信息也很重要。
【解决方案2】:

你可以使用exists:

select distinct
    colA
from
    mytable m1
where
    not exists (select 1 from mytable m2 where m2.colB = m1.colA)

exists 进行半连接以快速匹配值。 not in 完成整个结果集,然后对其执行orexists 对于表中的值通常更快。

【讨论】:

  • @Andrew - 当然!它说,抓住不同的colAs,其中没有来自mytable 的行,colB 等于colA
【解决方案3】:

您可以使用EXCEPT 运算符有效区分两个SELECT 查询。 EXCEPT DISTINCT 将只返回唯一值。 Oracle 的MINUS 运算符等价于EXCEPT DISTINCT

【讨论】:

    猜你喜欢
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2012-05-25
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多