runtime
25 / 88

lesson 25 Joins & sets · intermediate

ON versus WHERE in a LEFT JOIN

Place filters carefully when preserving unmatched rows.

the idea

ON decides which right-side rows may match. WHERE filters the joined output. Put a success condition in ON when you need to keep accounts with no successful requests.

tables in this lesson

The challenges use this data. Each column shows its type underneath; → marks a link to another table.

ai_accounts4 columns · 6 rows
idinteger · keyplantextregiontextsigned_up_attext
1proUS2025-01-01
2freeUS2025-01-02
3teamEU2025-01-02
4proIN2025-01-03
5freeEU2025-01-04

showing 5 of 6 rows

ai_requests7 columns · 12 rows
idinteger · keyaccount_idintegermodeltextrequested_attextinput_tokensintegeroutput_tokensintegerstatustext
11swift2025-01-01 10:00:001000200success
21reason2025-01-02 11:00:002000600success
32swift2025-01-02 12:00:005000error
43reason2025-01-02 13:00:0080002000success
53swift2025-01-03 14:00:0040001000success

showing 5 of 12 rows

example

The idea in one query. Press Run to see what it returns; running examples never affects your progress.

example.sql
SELECT a.id,COUNT(r.id) AS successful_requests
FROM ai_accounts a
LEFT JOIN ai_requests r ON r.account_id=a.id AND r.status='success'
GROUP BY a.id;

Watch for: A WHERE r.status filter discards unmatched accounts and changes the result.

build it step by step

Each step changes one thing. Run them in order and watch the result change.

  1. The dangerous filter. Filtering success in WHERE loses the account without successful requests.

    step-1.sql
    SELECT a.id,COUNT(r.id) AS successful_requests
    FROM ai_accounts a
    LEFT JOIN ai_requests r ON r.account_id=a.id
    WHERE r.status='success'
    GROUP BY a.id;
  2. Filter matching rows in ON. All accounts stay; only successful requests can match.

    step-2.sql
    SELECT a.id,COUNT(r.id) AS successful_requests
    FROM ai_accounts a
    LEFT JOIN ai_requests r ON r.account_id=a.id AND r.status='success'
    GROUP BY a.id;

challenge 1

Return id and successful_requests for every account, including zero successful requests.

Return idsuccessful_requestsany row order

challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.