Brightlane's CRM team is building a high-value customer list and needs to identify buyers with substantial order history.
Write a query to return the customer ID and total order count for every customer who has placed more than three orders.
Assumptions:
- The
orderstable contains every order Brightlane has processed. - The threshold (
> 3) applies to the per-customer count. - Each customer's order count is computed first, then the per-customer counts are narrowed to those above the threshold.
Output:
- One row per qualifying customer, with columns
customer_idandorder_count.
Schema · ecommerce 5 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
customer_id,
order_count
FROM
(
SELECT
customer_id,
COUNT(*) AS order_count
FROM
orders
GROUP BY
customer_id
) AS customer_orders
WHERE
order_count > 3 The shape
The inner query counts orders per customer and the outer query filters that result down to customers with more than three. The derived table is what lets WHERE reach a value — the per-customer count — that doesn't exist until after the grouping has run.
Clause by clause
- The inner block computes one row per customer with their order count:
SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_idFROM (...) AS customer_orderswraps that result as a derived table. The aliascustomer_ordersis mandatory — drop it and PostgreSQL raises a syntax error before the query runs.WHERE order_count > 3filters the derived table's rows.order_countis a real column at this layer, so a plainWHEREcomparison works the way it would against any table.SELECT customer_id, order_countreturns the two columns the CRM team's high-value list needs. The outer query can only see columns the innerSELECTexposed.
You practiced wrapping an aggregate query as a derived table so the outer query can filter on the aggregate result with WHERE. The recurring shape: any time aggregation produces a value that needs to be filtered, joined, or further aggregated, a derived table makes that second pass possible.