查询优化。没有NOT IN的查询

时间:2014-12-12 15:01:28

标签: mysql subquery query-optimization

我有一个包含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

2 个答案:

答案 0 :(得分:0)

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

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;

答案 1 :(得分:0)

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