Table Hierarchy & Schema
CREATE TABLE (reference)json
1CREATE TABLE users (2 user_id INTEGER PRIMARY KEY,3 email VARCHAR(255) NOT NULL UNIQUE,4 is_active BOOLEAN NOT NULL DEFAULT TRUE5);67CREATE TABLE orders (8 order_id INTEGER PRIMARY KEY,9 customer_id INTEGER NOT NULL,10 status VARCHAR(20) NOT NULL DEFAULT 'pending',11 total_amount DECIMAL(10, 2) NOT NULL,12 FOREIGN KEY (customer_id) REFERENCES users (user_id)13);Entity-Relationship Diagram
Optional relationship
The ER cardinality marker
||--o{ means a user may have zero or many orders — LEFT JOIN exposes the zero case.PK/FK Join Flow
Sample Data
usersjson
1| user_id | email | is_active |2|---------|---------------------|-----------|3| 1 | [email protected] | true |4| 2 | [email protected] | false |5| 3 | [email protected] | true |ordersjson
1| order_id | customer_id | status | total_amount |2|----------|-------------|----------|--------------|3| 1001 | 1 | paid | 49.99 |4| 1002 | 1 | shipped | 12.50 |5| 1003 | 3 | pending | 8.00 |[email protected] (user_id 2) has zero orders — the key scenario for LEFT JOIN.
Basic LEFT JOIN
All users with their orders (if any)json
1SELECT u.email, o.order_id, o.total_amount2FROM users u3LEFT JOIN orders o ON u.user_id = o.customer_id;Expected outputjson
1| email | order_id | total_amount |2|---|---|---|3| [email protected] | 1001 | 49.99 |4| [email protected] | 1002 | 12.50 |5| [email protected] | NULL | NULL |6| [email protected] | 1003 | 8.00 |Users With No Orders
Find customers who never orderedjson
1SELECT u.email2FROM users u3LEFT JOIN orders o ON u.user_id = o.customer_id4WHERE o.order_id IS NULL;Expected outputjson
1| email |2|---|3| [email protected] |INNER vs LEFT JOIN
| Join type | Keeps | Use when |
|---|---|---|
| INNER JOIN | Only rows with matches in both tables | You need related data only |
| LEFT JOIN | All left rows + matches or NULL | Include rows with zero matches on the right |
Constraints Reminder
| Constraint | Role in LEFT JOIN |
|---|---|
| PRIMARY KEY (user_id / order_id) | Uniquely identifies each row; join anchor |
| FOREIGN KEY (customer_id) | Order must reference a valid users.user_id |
| NOT NULL | Required columns cannot be missing on INSERT/UPDATE |
| UNIQUE (email) | No duplicate emails in users |
| DEFAULT (status, is_active) | Value applied when column omitted on INSERT |
Common Mistakes
- Putting filter conditions on the right table in WHERE instead of ON — can turn LEFT JOIN into INNER behavior.
- Using
= NULLinstead ofIS NULLwhen finding unmatched rows. - Assuming NULL means zero — NULL means unknown/no match.
Practice Prompts
- List every user email and order status, including users with no orders.
- Which inactive user has never placed an order?
- Rewrite an INNER JOIN query as LEFT JOIN and compare the row counts.
Try These Tools
Continue Learning
Frequently Asked Questions
What does LEFT JOIN return?
All rows from the left table. Matching right-table columns appear; non-matches show NULL in right-table columns.
Why does Bob appear with NULL order columns?
Bob has no orders. LEFT JOIN still returns his user row and fills order columns with NULL instead of dropping him.
LEFT JOIN vs INNER JOIN?
INNER keeps only matches. LEFT keeps every left row — use it when zero related rows is meaningful (e.g. users who never ordered).
How do I find users with no orders?
LEFT JOIN orders, then WHERE o.order_id IS NULL. This filters to left rows with no right match.
Can I LEFT JOIN multiple tables?
Yes. Chain joins left to right: FROM users u LEFT JOIN orders o … LEFT JOIN … Each preserves all rows from the leftmost table in that chain.