简体   繁体   中英

Query optimization. Query without NOT IN

I have a table with id and code entries. Codes are unique, but id is the primary key.

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

I need to find prefixes (first 3 letters) that don't have *999A entry. In the given example it'll be TRE and REW. My query is slow, it takes 17 seconds to run on ~9000 records. I understand it's mostly because I'm using NOT IN and subquery. Could anyone give me some ideas how to optimize it?

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

You can do a left join and then filter based on null values. It avoids the subquery, but I am not sure that this is the fastest solution.

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;

Although lp_'s solution is perfectly OK, I'd personally go for the much more readable syntax of 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' ) 

Should be similarly fast, if not faster, especially if there is a unique index/constraint on the newcode column.

PS: your original query had ORDER BY newcode while in fact said field is not part of the resultset. I presume you wanted to add ORDER BY Left(d1.newcode, 3)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM