Finding what's missing
Find the books nobody borrowed, or members who never borrowed.
LEFT JOIN, then keep the rows where the other table came back empty: IS NULL.
Show the name of every member who has never borrowed a book, so the library can send them a welcome offer.
Run your query to see the result table.
Press the green Run button or Ctrl+Enter.
How LEFT JOIN, IS NULL works
LEFT only keeps rows of the first table with no match.
members
| member_id | name |
|---|---|
| 101 | Ava |
| 102 | Ben |
| 103 | Cara |
| 104 | Dev |
loans
| loan_id | member_id | loan_date |
|---|---|---|
| 1 | 101 | 2026-01-12 |
| 2 | 103 | 2026-02-03 |
| 3 | 101 | 2026-03-20 |
| 4 | 102 | 2026-04-08 |
| 5 | 105(deleted) | 2026-05-14 |
query
SELECT members.name FROM members LEFT JOIN loans ON members.member_id = loans.member_id WHERE loans.loan_id IS NULL;
result: 1 row
| name |
|---|
| Dev |
Keeps only members with no match: Dev has never borrowed.
How do I find rows with no match?
FROM books LEFT JOIN loans ON books.book_id = loans.book_id WHERE loans.loan_id IS NULLLEFT JOINkeeps every book; the books with no loans have NULLs in the loans columns;IS NULLkeeps only those.Which column should
IS NULLtest?One that is never empty in the right-hand table, such as its id. A column that can be
NULLanyway (like returned) would also catch rows that did match.Is there another way?
WHERE book_id NOT IN (SELECT book_id FROM loans)reads more like English. Careful: if the inner list contains aNULL,NOT INreturns nothing at all.NOT EXISTSdoesn't have that trap.Why is this useful?
It answers "what's missing?": stock that never sells, customers who never ordered, invoices with no payment.
How is this like Excel?
Like
=ISNA(MATCH(A2, Loans!B:B, 0))filled down and filtered toTRUE, or Lookup & Merge's "Show what's missing".
How other databases do it
The lessons run on SQLite. Most of SQL is the same everywhere; these are the places where this lesson's SQL differs.
| Database | How | Note |
|---|---|---|
| SQLite (these lessons) | SELECT book_id FROM books EXCEPT SELECT book_id FROM loans | |
| PostgreSQL | EXCEPT | |
| MySQL / MariaDB | EXCEPT | Since MySQL 8.0.31. Before that, use LEFT JOIN or NOT EXISTS. |
| SQL Server | EXCEPT | |
| Oracle | MINUS | EXCEPT also works since Oracle 21c. |
| Sybase ASE | Not available | Use LEFT JOIN ... IS NULL, or NOT EXISTS. |
Know someone fighting with a spreadsheet? Send them this page.