Explain Codes LogoExplain Codes Logo

Mysql "NOT IN" query

sql
join
best-practices
performance
Alex KataevbyAlex Kataev·Jan 22, 2025
TLDR

NOT IN turns NULL in subqueries into party poopers. Avoid the party pooper using NOT EXISTS:

SELECT * FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.ref_id); -- Because not everyone's invited!

Or, pair your LEFT JOIN with a fashionable IS NULL for a performance boost on bigger parties:

SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.id = t2.ref_id WHERE t2.ref_id IS NULL; -- Uninvite those who never RSVP'd!

Keep the party going with this NULL-safe and typically more efficient approach.

Making NOT IN work

Sure, NOT IN has its quirks, but don't dismiss it just yet! It still has a place if:

  • Small guest lists: NOT IN works just fine when the list of exclusions isn't a mile long.
  • Simple syntax: Faster to type, easier to read, a real bang for your buck!
  • Legacy compatibility: Some old systems really get a kick out of NOT IN.

Just remember, avoid NULL at all costs—they empty your buffet!

SELECT * FROM users WHERE email NOT IN (SELECT email FROM unsubscribed_users WHERE email IS NOT NULL); -- RSVP only, no gatecrashers!

Beyond NOT IN: advanced syntax

Efficiency with LEFT JOIN / IS NULL

LEFT JOIN / IS NULL, your stylish alternative to NOT IN. Thanks to avoiding full table scans, it's like cruising in the fast lane. Also, MySQL promotes it to a NESTED LOOPS ANTI JOIN—a definite crowd-pleaser!

Example: Inviting cool people to your party:

SELECT t1.column1, t1.column2 FROM table1 t1 LEFT JOIN table2 t2 ON t1.matching_column = t2.matching_column WHERE t2.matching_column IS NULL; -- Because who invites party poopers?

The robust NOT EXISTS

NOT EXISTS might be less efficient, but it is your personal bodyguard against those nasty NULL values that can ruin NOT IN.

Round up your guests with:

SELECT column1, column2 FROM table1 t1 WHERE NOT EXISTS ( SELECT 1 FROM table2 t2 WHERE t1.matching_column = t2.matching_column ); -- Only cool kids allowed!

Gotcha! Syntax errors and version specifics

Remember to always update your MySQL, fixes syntax error quicker than you can say "syntax"! Some versions have specific optimizations; always handy, just like that corkscrew you never knew you needed!

Multi-table checks

Need to filter rudely based on many lists? Who doesn't? Use multiple LEFT JOIN statements combined with IS NULL:

SELECT t1.* FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.ref_id LEFT JOIN table3 t3 ON t1.id = t3.ref_id WHERE t2.ref_id IS NULL AND t3.ref_id IS NULL; -- Once, twice, three times - uninvited!

Avoid NULL values with NOT IN

Beware! A single NULL can turn NOT IN into a wild party out of control. Always filter out NULLs in your subquery:

SELECT fruit FROM basket WHERE fruit NOT IN (SELECT fruit FROM rotten_fruit WHERE fruit IS NOT NULL);

Errors, Mistakes and Boo-boos

Subqueries behaving badly with NOT IN might give incorrect results! Be on your toes for NULL values or cross-relation data. Remember, nothing kills a party like untested code or loose conditions!

Tips to keep your party lively

  • EXPLAIN: Like a guide to your party, reveals who's doing what and staying how long.
  • Indexes: Your party's waitstaff, ready to serve quick.
  • Watch the crowd: Keeping an eye on your tables (statistics, that is) helps you serve up the best parties!