Brightlane's CRM team wants a one-row summary per customer showing every status that customer has experienced across their order history.
Write a query to return every customer's ID and a comma-separated list of their order statuses, with the statuses arranged in alphabetical order within each list.
Assumptions:
- The
orderstable has one row per order with acustomer_idand astatus. - Each
customer_idwith at least one order should appear once in the result. - For each customer, the status list contains every
statusvalue across that customer's orders (one entry per order, no de-duplication), separated by', 'and arranged alphabetically.
Output:
- One row per customer with at least one order, with columns
customer_idandorder_statuses.
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,
STRING_AGG(
status,
', '
ORDER BY
status
) AS order_statuses
FROM
orders
GROUP BY
customer_id The shape
STRING_AGG(status, ', ' ORDER BY status) collapses every order belonging to one customer into a single text value, with the status of each order written out in alphabetical sequence. The CRM team gets one row per customer carrying the full history.
Clause by clause
SELECT customer_id, STRING_AGG(status, ', ' ORDER BY status) AS order_statusesreturns the customer's ID alongside their concatenated status list. The first argument names the column to collect; the second is the literal delimiter', 'placed between adjacent values. TheORDER BY statusinside the aggregate fixes the order the values join in, which is what gives'delivered, delivered, shipped'instead of an unpredictable arrangement.FROM ordersreads the order rows. Every order on file is in scope; the prompt asks for the full history per customer.GROUP BY customer_idpartitions the rows by customer so the aggregate runs once per customer instead of once across the whole table. One output row comes out for each distinctcustomer_id, which matches the "one row per customer" output spec.
Why this and not SUM or COUNT
Standard aggregates like SUM and COUNT collapse the rows in each group to a single number; the contributing values are gone. STRING_AGG is the aggregate that keeps them. Same grouping mechanics, different output shape: a delimited string carrying every value the group contributed.
You practiced STRING_AGG(column, separator ORDER BY column) — collect grouped values into a delimited text string with a deterministic order inside the aggregate.