SQL Quest › SQL Exercises › SQL GROUP BY and Aggregation
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.