从一列中选择不在另一列中的所有值的有效方法

时间:2012-01-05 03:03:26

标签: sql performance distinct notin

我需要返回colAcolB以外的所有值mytable。我正在使用:

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

它正在运行,但查询花费的时间过长。

有更有效的方法吗?

3 个答案:

答案 0 :(得分:15)

在标准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上设置索引才能使此查询更快。

答案 1 :(得分:6)

您可以使用exists

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

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

答案 2 :(得分:0)

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