Module 8 · SQL for Data Analysis
GROUP BY
Calculate totals and counts for each customer, route, month or status.
About 30 minutes
The problem
Harbourline has thousands of shipment records. Your manager wants to know:
"Which customers have shipped the most containers this year?"
You know how to add up containers for the whole company with SUM. Now you need that total for each customer, then the biggest ones at the top.
The concept
GROUP BY splits the rows into groups that share a value, then runs your aggregate functions once per group.
Think of it as sorting shipment slips into piles, one pile per customer, then counting the containers in each pile.
Two rules keep you out of trouble:
- Every column in
SELECTmust either be inGROUP BYor be inside an aggregate function. GROUP BYcomes afterWHEREand beforeORDER BY.
SQL
SELECT … FROM … WHERE … GROUP BY … ORDER BY … LIMIT …Example
SELECT
customer_id,
COUNT(*) AS shipments,
SUM(containers) AS containers
FROM shipments
WHERE booking_date >= '2026-01-01'
GROUP BY customer_id
ORDER BY containers DESC
LIMIT 10;Walkthrough
Line by line:
FROM shipments WHERE booking_date >= '2026-01-01'takes this year's shipments.GROUP BY customer_idmakes one group per customer.COUNT(*)counts the shipments in each group, andSUM(containers)adds up their containers.ORDER BY containers DESCputs the biggest shippers first. Herecontainersrefers to the alias you created.LIMIT 10keeps the top ten.
The result has one row per customer, not one per shipment. You'll see customer IDs rather than names, because names live in the customers table. You'll join the two in the JOINs lesson.
You can group by more than one column. This counts customers for each city and industry combination:
SELECT city, industry, COUNT(*) AS customers
FROM customers
GROUP BY city, industry
ORDER BY city, customers DESC;Each row is one city and industry pair, with the number of customers in it.
You can also group by a calculated value. strftime('%Y-%m', booking_date) turns a date into its year and month, which gives monthly totals:
SELECT
strftime('%Y-%m', booking_date) AS month,
COUNT(*) AS shipments
FROM shipments
GROUP BY month
ORDER BY month;Practice
Practice
How many shipments are there in each status? Show status and a count named shipments.
Ctrl + Enter to run. Tab indents; press Esc then Tab to leave the editor.
Practice
What is the total freight_charge for each route_id? Show route_id and total_charge, highest total first.
Ctrl + Enter to run. Tab indents; press Esc then Tab to leave the editor.
Challenge
Challenge · optional
Finance wants money received per month in 2026. Show the month (as 'YYYY-MM') and the total payment amount, in date order. Use the payments table.
Ctrl + Enter to run. Tab indents; press Esc then Tab to leave the editor.
Check your understanding
Answer every question to check.