Joins
Join Then Filter
High-Value Matches
A joined result can still be filtered. The WHERE condition can reference either table.
Program
Play the query to keep only high-value customer orders.
join_filter.sql
Replay: real traced execution (multi-file project)
CREATE TABLE customers (id INTEGER, name TEXT);
CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);
INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');
INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);
WITH params(min_total) AS (VALUES (20)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;
CREATE TABLE customers (id INTEGER, name TEXT);
CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);
INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');
INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);
WITH params(min_total) AS (VALUES (10)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;
CREATE TABLE customers (id INTEGER, name TEXT);
CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);
INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');
INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);
WITH params(min_total) AS (VALUES (31)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;
customers ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);values this step0 rowscustomersorders ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');values this step0 rowsorderscustomers ← 2 rows
2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);values this step2 rowscustomersorders ← 3 rows
3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (20)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step3 rowsordersresult ← 1 row
4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (20)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step1 rowresult
customers ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);values this step0 rowscustomersorders ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');values this step0 rowsorderscustomers ← 2 rows
2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);values this step2 rowscustomersorders ← 3 rows
3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (10)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step3 rowsordersresult ← 2 rows
4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (10)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step2 rowsresult
customers ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);values this step0 rowscustomersorders ← 0 rows
1CREATE TABLE customers (id INTEGER, name TEXT);2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');values this step0 rowsorderscustomers ← 2 rows
2CREATE TABLE orders (id INTEGER, customer_id INTEGER, total INTEGER);3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);values this step2 rowscustomersorders ← 3 rows
3INSERT INTO customers VALUES (1, 'Ada'), (2, 'Lin');4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (31)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step3 rowsordersresult ← 0 rows
4INSERT INTO orders VALUES (101, 1, 30), (102, 2, 12), (103, 1, 8);5WITH params(min_total) AS (VALUES (31)) SELECT customers.name, orders.total FROM customers JOIN orders ON customers.id = orders.customer_id WHERE orders.total >= (SELECT min_total FROM params) ORDER BY orders.total DESC;values this step0 rowsresult
Join, Then Filter
- First, join customers to matching orders.
- Next, check each joined row's order total.
- Keep only rows where the total passes the
WHERErule. - Sort the kept rows so the highest totals appear first.
| Joined row total | Filter result |
| --- | --- |
|
15| removed | |31| kept |
join filter
`WHERE orders.total >= 20` filters the joined rows.
DESC
`ORDER BY ... DESC` sorts high values first.
composition
Joins, filters, and sorting compose in one query.
Exercise: join_filter.sql
Join customers to orders, keep only totals at least 20, and sort highest totals first