SQL GROUP BY and Aggregation Practice — 147 Challenges (111 Free)

147 hands-on challenges counted from the live bank — 30 Easy, 76 Medium, 41 Hard — every one on the skill radar's Aggregation & Grouping axis: COUNT and SUM over a whole table, GROUP BY on one key or on several, HAVING to filter the groups you just made, and the COUNT(DISTINCT …) trap. 111 are free to play, including 5 free Hard previews; the rest are Pro. Real datasets, AI tutoring.

Start Practicing Free →

More than half the bank touches aggregation, so this page does not put every one of them on a card. The five sections below are the five shapes the work takes, each a predicate over the reference solution — an aggregate with no GROUP BY, one grouping key on one table, two or more keys, a HAVING clause, a COUNT(DISTINCT …) — and each lists every challenge in the bank that matches it, so a section is complete even though the page is a selection. What is left out aggregates inside a join, a window function, a CTE, a subquery or a CASE: that is what the joins, window functions, CTE, subquery and CASE WHEN pages are organised around.

Aggregate functions over a whole table: 8 challenges (8 free)

No GROUP BY at all — COUNT(*), SUM(amount), AVG(price), MIN and MAX collapse every row that survived the WHERE into a single answer. Start with Counting Rows, then SUM, AVG, MIN, MAX: the two written for the syntax. Every one here is Easy and free, and three of them run on real public data — FDIC deposits, NYC assessed values, factory sensor readings. The cheat sheet has the whole list on one screen.

Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.

Easy Free

Counting Rows

Uses: COUNT Aggregation

Try it →
Easy Free

SUM, AVG, MIN, MAX

Uses: Aggregation ROUND

Try it →
Easy Free

How Many Genres Do We Cover? (DISTINCT)

Uses: COUNT DISTINCT Aggregation

Try it →
Easy Free

Female Survivor Count

Uses: COUNT WHERE Aggregation

Try it →
Easy Free

National Total Deposits

Finance & Banking track · Uses: Aggregation SUM

Try it →
Easy Free

Total Assessed Value

Uses: Aggregation SUM

Try it →
Easy Free

Average Sensor Readings

Manufacturing & Industry track · Uses: Aggregation AVG

Try it →
Easy Free

Failure Count by Mode

Manufacturing & Industry track · Uses: Aggregation SUM

Try it →

Your first GROUP BY — one key, one table: 19 challenges (19 free)

One grouping key, one table, no HAVING: SELECT department, COUNT(*) FROM employees GROUP BY department. The rule that catches everyone is that every column in the SELECT list is either aggregated or named in the GROUP BY — SQLite will happily return a value from an arbitrary row instead of erroring. Start with GROUP BY Basics; Monthly Order Count and Day-of-Week Order Pattern (strftime) group by an expression rather than a column, which is the next step. The GROUP BY tutorial walks the mental model.

Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.

Easy Free

GROUP BY Basics

Uses: GROUP BY Aggregation

Try it →
Easy Free

Monthly Order Count

Uses: GROUP BY Date Functions strftime

Try it →
Easy Free

Average Salary by Department

Uses: GROUP BY AVG ROUND Aggregation

Try it →
Easy Free

Movie Title Initial Letter Histogram (SUBSTR)

Uses: GROUP BY SUBSTR String Functions

Try it →
Easy Free

Bank Count Per State

Finance & Banking track · Uses: GROUP BY Aggregation ORDER BY

Try it →
Easy Free

Properties Per Borough

Uses: GROUP BY Aggregation ORDER BY

Try it →
Easy Free

Quality Grade Distribution

Manufacturing & Industry track · Uses: GROUP BY Aggregation

Try it →
Easy Free

Chargeback Reason Codes: Resolved and Still Open

Finance & Banking track · Uses: GROUP BY Aggregation IS NULL ORDER BY

Try it →
Easy Free

The Ledger's First Week, Day by Day

Finance & Banking track · Uses: WHERE GROUP BY Date Functions AVG

Try it →
Medium Free

Class Survival Breakdown

Uses: GROUP BY Aggregation

Try it →
Medium Free

Full Survival Dashboard by Class

Uses: GROUP BY Aggregation ORDER BY

Try it →
Medium Free

Monthly Order Trends

Uses: Date Functions GROUP BY Aggregation ORDER BY

Try it →
Medium Free

Senior Passengers by Port

Uses: WHERE GROUP BY Aggregation NULL Handling

Try it →
Medium Free

Monthly Order Volume in 2024

Uses: Date Functions strftime GROUP BY Aggregation

Try it →
Medium Free

Department Tenure Span

Uses: GROUP BY Aggregation Date Functions JULIANDAY

Try it →
Medium Free

Day-of-Week Order Pattern (strftime)

Uses: GROUP BY Date Functions strftime

Try it →
Medium Free

Failed Banks Recent Decade

Finance & Banking track · Uses: WHERE Date Functions Aggregation GROUP BY

Try it →
Medium Free

Avg DEED Amount Per Borough

Uses: JOIN GROUP BY Aggregation JOIN + GROUP BY

Try it →
Medium Free

How Long Has Each Card Been Active?

Finance & Banking track · Uses: GROUP BY Aggregation Date Functions JULIANDAY

Try it →

Grouping by two or more keys: 32 challenges (20 free)

Add a key and the grain of the answer changes: GROUP BY country, category gives one row per pair, not one per country. This is where cross-tabs, cohort tables and per-group top-N live, and where a fanned-out join quietly doubles your SUM. Start with Counting Across a JOIN, then Survival Cross-Tab: Class × Sex; the Hard ones carry the pairs through CTEs and window functions.

Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.

Easy Free

Counting Across a JOIN

Uses: JOIN GROUP BY COUNT

Try it →
Easy Free

Monthly Spend Per Account

Finance & Banking track · Uses: GROUP BY SUM strftime GROUP BY + Date Functions

Try it →
Medium Free

LEFT JOIN: Keep Everyone

Uses: LEFT JOIN GROUP BY

Try it →
Medium Free

LEFT JOIN NULL Semantics: Inactive Customers

Uses: LEFT JOIN COALESCE Aggregation GROUP BY

Try it →
Medium Free

Count Direct Reports

Uses: JOIN GROUP BY Aggregation Self-Join

Try it →
Medium Free

Quarterly Hiring Cohort Report

Uses: Date Functions CASE GROUP BY Aggregation

Try it →
Medium Free

Survival Cross-Tab: Class × Sex

Uses: GROUP BY Aggregation ORDER BY

Try it →
Medium Free

Customer Recency Analysis

Uses: JOIN GROUP BY Date Functions Aggregation

Try it →
Medium Free

Multi-Month Active Customers

Uses: JOIN GROUP BY HAVING COUNT DISTINCT

Try it →
Medium Free

Inactive Customers by Tier

Uses: LEFT JOIN CASE GROUP BY Derived Table

Try it →
Medium Free

Month-over-Month Customer Growth

Uses: GROUP BY Aggregation Window Functions LAG

Try it →
Medium Free

Country × Category Coverage Matrix (Cross Join)

Uses: CROSS JOIN LEFT JOIN COUNT Cross Join

Try it →
Medium Free

Membership × Country Activity (Cross Join)

Uses: CROSS JOIN LEFT JOIN GROUP BY Cross Join

Try it →
Medium Free

Bank with Branch Count and Income

Finance & Banking track · Uses: JOIN GROUP BY Aggregation Multi-JOIN

Try it →
Medium Free

Failure Clustering — State + Year

Finance & Banking track · Uses: GROUP BY HAVING Date Functions

Try it →
Medium Free

Geographic Concentration — Single-State Banks

Finance & Banking track · Uses: JOIN GROUP BY Aggregation CASE

Try it →
Medium Free

Top 3 Merchants Per Category by Spend

Finance & Banking track · Uses: Window Functions ROW_NUMBER PARTITION BY JOIN

Try it →
Medium Free

Chargeback Rate Per Merchant

Finance & Banking track · Uses: JOIN LEFT JOIN GROUP BY HAVING

Try it →
Medium Free

Cardholders Who Have Never Disputed a Charge

Finance & Banking track · Uses: Subquery JOIN GROUP BY SUM

Try it →
Medium Free

Busiest Merchants, and What a Tie Does to the Rank

Finance & Banking track · Uses: Window Functions RANK ROW_NUMBER JOIN

Try it →
Hard Pro

Recursive Team Size Rollup

Uses: Recursive CTE CTE JOIN Aggregation

Try it →
Hard Pro

Top Spender Per Country

Uses: Subquery GROUP BY HAVING Aggregation

Try it →
Hard Pro

Customer Lifetime Value

Uses: JOIN GROUP BY Aggregation ORDER BY

Try it →
Hard Pro

Engagement Streaks (3+ Orders, ≤7-Day Gaps)

Uses: CTE Window Functions LAG Running Total

Try it →
Hard Pro

Top-N Products per Category

Uses: CTE Window Functions ROW_NUMBER PARTITION BY

Try it →
Hard Pro

Anti-Join Pipeline: Unmatched Records

Uses: LEFT JOIN IS NULL CTE GROUP BY

Try it →
Hard Pro

Top Spender per Membership Tier

Uses: CTE JOIN Window Function Aggregation

Try it →
Hard Pro

Customer Retention Cohort

Uses: CTE MIN Date Functions GROUP BY

Try it →
Hard Pro

YoY Sales Volume Per Borough

Uses: Window Functions LAG Date Functions GROUP BY

Try it →
Hard Pro

Failure Rate by Torque Bucket

Manufacturing & Industry track · Uses: CTE JOIN CASE GROUP BY

Try it →
Hard Pro

Velocity Rule — 5+ Transactions in 5 Minutes

Finance & Banking track · Uses: JOIN GROUP BY Date Functions Self-Join

Try it →
Hard Pro

Cards That Never Spend at Home

Finance & Banking track · Uses: JOIN GROUP BY HAVING CASE

Try it →

HAVING — filter the groups, not the rows: 30 challenges (21 free)

WHERE runs before the grouping and HAVING after it, so a condition on COUNT(*) or SUM(total) can only ever be a HAVING — and a condition on a plain column belongs in WHERE, where it throws rows away before they cost anything. Start with High-Volume Categories (HAVING), then GROUP BY + HAVING, both written for the clause. WHERE vs HAVING has the execution order in one diagram.

Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.

Easy Free

High-Volume Categories (HAVING)

Uses: GROUP BY HAVING COUNT

Try it →
Easy Free

States With 5 or More Banks

Finance & Banking track · Uses: GROUP BY HAVING Aggregation

Try it →
Easy Free

Common Building Classes

Uses: GROUP BY HAVING Aggregation

Try it →
Easy Free

Quality Grades With 100+ Products

Manufacturing & Industry track · Uses: GROUP BY HAVING Aggregation

Try it →
Medium Free

GROUP BY + HAVING

Uses: GROUP BY HAVING Aggregation

Try it →
Medium Free

Count Direct Reports

Uses: JOIN GROUP BY Aggregation Self-Join

Try it →
Medium Free

Genre Financial Report

Uses: GROUP BY HAVING Aggregation CASE

Try it →
Medium Free

Department Compensation Report

Uses: GROUP BY HAVING Aggregation CASE

Try it →
Medium Free

Consistent Director Analysis

Uses: GROUP BY HAVING Aggregation Subquery

Try it →
Medium Free

Highest Total Salary Budget Department

Uses: GROUP BY Aggregation Subquery HAVING

Try it →
Medium Free

Title Social Survival Analysis

Uses: GROUP BY Aggregation HAVING CASE

Try it →
Medium Free

Find Duplicate Emails

Uses: GROUP BY HAVING Aggregation GROUP BY + HAVING

Try it →
Medium Free

Highest Rated by Genre

Uses: Subqueries Aggregation WHERE GROUP BY

Try it →
Medium Free

Director Consistency Report

Uses: GROUP BY HAVING Aggregation Subquery

Try it →
Medium Free

Multi-Month Active Customers

Uses: JOIN GROUP BY HAVING COUNT DISTINCT

Try it →
Medium Free

Director Rating Volatility

Uses: GROUP BY HAVING Aggregation MIN

Try it →
Medium Free

Active Spender Cohort (HAVING)

Uses: GROUP BY HAVING Aggregation

Try it →
Medium Free

Genre-Spanning Directors (HAVING)

Uses: GROUP BY HAVING COUNT DISTINCT

Try it →
Medium Free

Average Tier 1 Ratio Per State

Finance & Banking track · Uses: JOIN GROUP BY Aggregation HAVING

Try it →
Medium Free

Failure Clustering — State + Year

Finance & Banking track · Uses: GROUP BY HAVING Date Functions

Try it →
Medium Free

Chargeback Rate Per Merchant

Finance & Banking track · Uses: JOIN LEFT JOIN GROUP BY HAVING

Try it →
Hard Pro

RANK vs DENSE_RANK: Rating Gaps

Uses: Window Functions RANK DENSE_RANK ROW_NUMBER

Try it →
Hard Pro

Top Spender Per Country

Uses: Subquery GROUP BY HAVING Aggregation

Try it →
Hard Pro

Moving Average with Dynamic Window

Uses: Window Functions Frame Clause CTE GROUP BY

Try it →
Hard Pro

Passenger Family Survival Analysis

Uses: String Functions GROUP BY HAVING Aggregation

Try it →
Hard Pro

Engagement Streaks (3+ Orders, ≤7-Day Gaps)

Uses: CTE Window Functions LAG Running Total

Try it →
Hard Pro

Customers with Orders in ALL Categories

Uses: GROUP BY HAVING COUNT DISTINCT

Try it →
Hard Pro

Active Properties with Permits

Uses: CTE JOIN GROUP BY Subquery

Try it →
Hard Pro

Velocity Rule — 5+ Transactions in 5 Minutes

Finance & Banking track · Uses: JOIN GROUP BY Date Functions Self-Join

Try it →
Hard Pro

Cards That Never Spend at Home

Finance & Banking track · Uses: JOIN GROUP BY HAVING CASE

Try it →

COUNT(DISTINCT x) against COUNT(*): 12 challenges (7 free)

COUNT(*) counts rows, COUNT(x) counts the rows where x is not NULL, and COUNT(DISTINCT x) counts different values — after a join those are three different answers, and picking the wrong one is the most common wrong number in an analytics dashboard. Start with How Many Genres Do We Cover? (DISTINCT); Daily Active Customers and Customer Retention Cohort are the shape an interview asks for.

Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.

Easy Free

How Many Genres Do We Cover? (DISTINCT)

Uses: COUNT DISTINCT Aggregation

Try it →
Easy Free

Signup-Month Cohort Spend

Finance & Banking track · Uses: JOIN GROUP BY COUNT DISTINCT strftime

Try it →
Easy Free

Card Spend by Country

Finance & Banking track · Uses: JOIN GROUP BY COUNT DISTINCT Aggregation

Try it →
Medium Free

Category Revenue with Relabeling

Uses: CASE GROUP BY Aggregation ORDER BY

Try it →
Medium Free

Membership Tier Revenue Analysis

Uses: LEFT JOIN GROUP BY Aggregation COALESCE

Try it →
Medium Free

Multi-Month Active Customers

Uses: JOIN GROUP BY HAVING COUNT DISTINCT

Try it →
Medium Free

Genre-Spanning Directors (HAVING)

Uses: GROUP BY HAVING COUNT DISTINCT

Try it →
Hard Pro

Daily Active Customers

Uses: GROUP BY Aggregation COUNT DISTINCT GROUP BY + Date Functions

Try it →
Hard Pro

Anti-Join Pipeline: Unmatched Records

Uses: LEFT JOIN IS NULL CTE GROUP BY

Try it →
Hard Pro

Customers with Orders in ALL Categories

Uses: GROUP BY HAVING COUNT DISTINCT

Try it →
Hard Pro

Customer Retention Cohort

Uses: CTE MIN Date Functions GROUP BY

Try it →
Hard Pro

Cards That Never Spend at Home

Finance & Banking track · Uses: JOIN GROUP BY HAVING CASE

Try it →

Aggregation is the skill the rest of the bank is built on, so it also turns up wherever the other topics do. If you want it with a join, a window frame or a CTE around it, the sibling pages list those: joins, window functions, CTEs, subqueries and CASE WHEN.