查询优化。不带 NOT IN 的查询

Posted

技术标签:

【中文标题】查询优化。不带 NOT IN 的查询【英文标题】:Query optimization. Query without NOT IN 【发布时间】:2014-12-12 15:01:27 【问题描述】:

我有一个包含 id 和代码条目的表。代码是唯一的,但 id 是主键。

ID Code 
1 ABC1234T
2 ABC6789Y
3 ABC9999A
4 QAZ1234G
5 QAZ6574U
6 QAZ9999A
7 TRE1234Y
8 REW1234U

我需要找到没有 *999A 条目的前缀(前 3 个字母)。在给定的示例中,它将是 TRE 和 REW。我的查询很慢,大约 9000 条记录需要 17 秒才能运行。我知道这主要是因为我使用的是 NOT IN 和子查询。谁能给我一些如何优化它的想法?

SELECT distinct LEFT(newcode, 3) as codeprefix FROM diatcode where (LEFT(newcode, 3)) NOT in (select DISTINCT LEFT(newcode, 3) from diatcode where newcode like '___9999A' ) order by newcode

【问题讨论】:

【参考方案1】:

您可以进行左连接,然后根据空值进行过滤。它避免了子查询,但我不确定这是最快的解决方案。

SELECT DISTINCT LEFT(d1.newcode, 3) as codeprefix
FROM diatcode d1
LEFT JOIN (SELECT DISTINCT LEFT(d2.newcode, 3) as codeprefix
  FROM diatcode d2
  WHERE d2.newcode LIKE '___9999A') t2
ON LEFT(d1.newcode, 3)=t2.codeprefix
WHERE t2.codeprefix IS NULL;

【讨论】:

谢谢!这次用了 0.2 秒。 那么至少是一个快速的解决方案:) 感谢您的反馈【参考方案2】:

虽然 lp_ 的解决方案完全没问题,但我个人会选择WHERE NOT EXISTS() 的可读性更强的语法

SELECT distinct LEFT(d1.newcode, 3) as codeprefix 
  FROM diatcode d1
 WHERE NOT EXISTS ( SELECT *
                      FROM diatcode d2
                     WHERE d2.newcode = LEFT(d1.newcode, 3) + '9999A' ) 

应该同样快,如果不是更快的话,尤其是在 newcode 列上有唯一索引/约束的情况下。

PS:您的原始查询具有 ORDER BY newcode 而实际上所述字段不是结果集的一部分。我猜你想添加ORDER BY Left(d1.newcode, 3)

【讨论】:

以上是关于查询优化。不带 NOT IN 的查询的主要内容,如果未能解决你的问题,请参考以下文章

发送 get 请求时不带括号返回

除非必要,价格不带小数

CSS Div 向上滑动不带内容

位置固定页脚,不带JavaScript

Spark(1.6) Densevector.type 不带参数

通过API设置Twitter状态(不带oAuth)