Python Central HubSign in

Data Analytics with Python / Phase 9: SQL for Data Analytics

Aggregations (COUNT, SUM, AVG) and GROUP BY

Compute metrics with SQL aggregations and group them by dimensions.

Aggregation functions

Common analytics aggregations:

  • COUNT(*): number of rows
  • COUNT(DISTINCT user_id): unique users
  • SUM(amount): total revenue
  • AVG(amount): average order amount
  • MIN(), MAX()
SQL
SELECT
  COUNT(*) AS orders,
  SUM(amount) AS revenue,
  AVG(amount) AS avg_order_value
FROM orders;

GROUP BY

Group by a dimension:

SQL
SELECT
  u.country,
  COUNT(*) AS orders,
  SUM(o.amount) AS revenue
FROM orders o
JOIN users u ON u.user_id = o.user_id
GROUP BY u.country
ORDER BY revenue DESC;

HAVING

HAVING filters groups (after aggregation).

SQL
SELECT
  u.country,
  COUNT(*) AS orders
FROM orders o
JOIN users u ON u.user_id = o.user_id
GROUP BY u.country
HAVING COUNT(*) >= 100
ORDER BY orders DESC;

Tip: avoid common mistakes

  • Every selected non-aggregated column must be in GROUP BY.
  • WHERE filters rows before grouping; HAVING filters after.

Mental model: split → aggregate → combine

GROUP BY works the same way in every SQL dialect: rows are split into buckets by the grouping column, an aggregate function collapses each bucket to one number, and the buckets are combined back into a result table — one row per group.

diagram GROUP BY pipeline mermaid
Rows are split into buckets by the grouping column, each bucket is collapsed by an aggregate, then combined into one row per group.
sketch Rows collapsing into grouped totals p5.js
Each colored dot is one order row; rows with the same country collapse into a single aggregated bar.

Check your understanding

quizCheck yourself
  1. Which expression counts unique customers in the orders table?

    Show answer

    B — COUNT(DISTINCT user_id) — COUNT(*) counts rows, while COUNT(DISTINCT user_id) counts unique users.

  2. What is the difference between WHERE and HAVING?

    Show answer

    A — WHERE filters rows before grouping and HAVING filters groups after aggregation — HAVING COUNT(*) >= 100 can only be evaluated after groups exist.

  3. In the revenue by country query, what happens if you select u.country and leave it out of GROUP BY?

    Show answer

    B — It breaks the rule that every non-aggregated selected column must be in GROUP BY — Every selected non-aggregated column must be in GROUP BY, or the query is ambiguous.

  4. Which COUNT variant skips NULL values in the column?

    Show answer

    C — COUNT(column) — COUNT(column) ignores NULLs, while COUNT(*) counts every row.

🧪 Try It Yourself

Exercise 1 – COUNT and SUM

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – GROUP BY a dimension

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – HAVING filters groups

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Next

Now that you can summarize one table, Joins (INNER, LEFT) for Analytics shows you how to bring columns from other tables into that same aggregation.

Was this page helpful?

Let us know how we did