SQL Anti-Join Pattern
The formal name for 'rows in A with no match in B' — everything from the last two lessons, named properly.
What & Why
An anti-join returns rows from one table that have no corresponding match in another. It's not a distinct SQL keyword — it's the name for the pattern you get from NOT EXISTS or LEFT JOIN ... WHERE NULL.
See How It Works
BUSINESS QUESTION
Product wants features that have never received feedback.
| id | name | description | team | released_at | deprecated_at |
|---|---|---|---|---|---|
| 1 | Activation Checklist | Guides new users through setup | growth | 2024-01-20 | NULL |
| 2 | CSV Export | Exports report data | platform | 2024-02-14 | NULL |
| 3 | Invite Nudges | Prompts workspace collaboration | growth | 2024-03-05 | NULL |
| 4 | Legacy Dashboard | Original reporting surface | analytics | 2023-08-10 | 2024-06-01 |
| id | user_id | feature_id | rating | nps_score | comment | created_at |
|---|---|---|---|---|---|---|
| 1 | 101 | 1 | 5 | 9 | Clear and useful | 2024-01-25 12:15:00+00 |
| 2 | 102 | 2 | 4 | NULL | Export worked well | 2024-02-20 15:40:00+00 |
| 3 | 103 | 1 | 4 | 7 | Helpful setup flow | 2024-03-18 09:05:00+00 |
| 4 | 104 | 3 | 3 | NULL | Needs clearer timing | 2024-04-08 17:30:00+00 |
Watch NOT EXISTS keep the feature with no feedbackStep 1 of 4
NOT EXISTS product.feedback where feedback.feature_id = feature.id
| feature_id | feature | feedback_ids | decision |
|---|---|---|---|
| 1 | Activation Checklist | 1, 3 | SKIP |
| 2 | CSV Export | 2 | SKIP |
| 3 | Invite Nudges | 4 | SKIP |
| 4 | Legacy Dashboard | — | KEEP |
Activation Checklist has two feedback rows.
EXAMPLE QUERY
SELECT
f.id AS feature_id,
f.name
FROM product.features f
WHERE NOT EXISTS (
SELECT 1
FROM product.feedback fb
WHERE fb.feature_id = f.id
)
ORDER BY feature_id;This lesson's practice is part of Pro.
Sign up free to try it on a real business scenario