SQL Quest › SQL Exercises › SQL Subqueries
SQL Subquery Practice — 57 Challenges (42 Free)
57 challenges whose reference solution uses a subquery — a SELECT in parentheses that is not a CTE — counted from the live bank: 8 Easy, 32 Medium, 17 Hard. 42 are free to play, including 2 free Hard previews; the rest are Pro. If the shape is new, take the on-ramp in order: A Subquery That Returns One Value, A Subquery That Returns a Set (IN), then Filter on an Average You Just Computed, which is a whole query sitting in the FROM clause. After that the Medium ladder is wide. Real datasets, AI tutoring.
Start Practicing Free →
Prefer to name the step instead of nesting it? CTE vs subquery vs temp table settles when the choice matters, and the CTE challenges are the WITH-clause side of the same bank.
A subquery as a value or a list — scalar and IN: 36 challenges (25 free)
WHERE salary > (SELECT AVG(salary) FROM employees) — the inner query runs once and returns one value; WHERE customer_id IN (SELECT …) returns a list to match against. The Easy on-ramps are here: A Subquery That Returns One Value, then the same shape on a second schema in Movies Rated Above the Average; then A Subquery That Returns a Set (IN), and Every Film by a Director Who Once Hit 8.5, where the list comes out of the table you are already selecting from. The Medium ones move the scalar into the SELECT list, into HAVING, inside COALESCE; the Hard ones nest it inside a CTE or divide by it for a share. Mind NOT IN against a nullable column — the NOT IN trap.
Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard.
Easy Free
A Subquery That Returns One Value
Uses: Subquery WHERE
Try it →
Easy Free
Movies Rated Above the Average
Uses: Subquery WHERE
Try it →
Easy Free
A Subquery That Returns a Set (IN)
Uses: Subquery IN WHERE
Try it →
Easy Free
Every Film by a Director Who Once Hit 8.5
Uses: Subquery IN WHERE
Try it →
Easy Free
Transaction Share by Merchant Category
Uses: Subquery JOIN GROUP BY
Try it →
Easy Free
Better Than Its Own Genre
Uses: Subquery Correlated Subquery WHERE
Try it →
Medium Free
Handle NULL Ages
Uses: NULL Handling COALESCE Aggregation GROUP BY
Try it →
Medium Free
Simple Subquery: Above Average
Uses: Subquery WHERE
Try it →
Medium Free
Subquery in FROM (Derived Table)
Uses: Subquery Derived Table JOIN GROUP BY
Try it →
Medium Free
Consistent Director Analysis
Uses: GROUP BY HAVING Aggregation Subquery
Try it →
Medium Free
Below Department Average
Uses: Subquery WHERE Aggregation
Try it →
Medium Free
Highest Total Salary Budget Department
Uses: GROUP BY Aggregation Subquery HAVING
Try it →
Medium Free
Fare Imputation Analysis
Uses: NULL Handling COALESCE GROUP BY Aggregation
Try it →
Medium Free
Genres Without Blockbusters
Uses: Subquery NOT IN DISTINCT NOT IN / Subquery
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
Above-Department-Average Earners
Uses: Subquery Correlated Subquery
Try it →
Medium Free
Delete Duplicate Records, Keep the Original
Uses: DELETE DML Subquery Aggregation
Try it →
Medium Free
Recompute a Stale Counter
Uses: UPDATE DML Correlated Subquery Aggregation
Try it →
Medium Free
Banks Above National Average Assets
Finance & Banking track · Uses: WHERE Subquery
Try it →
Medium Free
Above-Median NPL Banks
Finance & Banking track · Uses: CTE JOIN Subquery
Try it →
Medium Free
Above-Average-Assess Properties
Real Estate track · Uses: WHERE Subquery
Try it →
Medium Free
Above-Average Tool Wear
Manufacturing & Industry track · Uses: WHERE Subquery
Try it →
Medium Free
ROA Outliers — Top 5% by Return
Finance & Banking track · Uses: Subquery JOIN ORDER BY
Try it →
Medium Free
Dormant Cards — No Transactions in the Last 14 Days
Uses: LEFT JOIN IS NULL CTE
Try it →
Hard Pro
Correlated Subquery: Employees Above Department Median
Uses: Correlated Subquery COUNT WHERE
Try it →
Hard Pro
Wealthy Survivor Profile
Uses: WHERE Subquery ORDER BY
Try it →
Hard Pro
Top Spender Per Country
Uses: Subquery GROUP BY HAVING Aggregation
Try it →
Hard Pro
Highest Fare Per Port
Uses: Subquery WHERE Aggregation ORDER BY
Try it →
Hard Pro
Order Status Dashboard
Uses: GROUP BY Aggregation Subquery ORDER BY
Try it →
Hard Pro
Anti-Join Pipeline: Unmatched Records
Uses: LEFT JOIN IS NULL CTE GROUP BY
Try it →
Hard Pro
Department Budget Analysis
Uses: CTE Aggregation GROUP BY Subquery
Try it →
Hard Pro
Customers with Orders in ALL Categories
Uses: GROUP BY HAVING COUNT DISTINCT
Try it →
Hard Pro
QoQ Asset Growth — Top Banks
Finance & Banking track · Uses: Window Functions LAG JOIN
Try it →
Hard Pro
Banks with NPL Above 2-Sigma
Finance & Banking track · Uses: CTE Aggregation Subquery Statistics
Try it →
Hard Pro
How Concentrated Is the Spend?
Uses: Subquery CTE ROW_NUMBER CASE
Try it →
Derived tables — a subquery in FROM: 18 challenges (13 free)
Aggregate first, then query the result — FROM (SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department) d. Start with Filter on an Average You Just Computed, the Easy one — a country average computed in FROM and then filtered with a plain WHERE — then Subquery in FROM (Derived Table) and Above-Average Departments. The Hard ones wrap a window function you cannot filter in the same SELECT — ROW_NUMBER, LAG, a running SUM — and Running Total Revenue and Year-over-Year Growth are the 2 free Hard previews. Three sector ones wrap a UNION ALL. A derived table is the case where a CTE reads better; the CTE tutorial shows the rewrite.
Counted from the challenge bank, September 2026. Easy first, then Medium, then Hard — previews before Pro.
Easy Free
Filter on an Average You Just Computed
Uses: Subquery Derived Table Aggregation GROUP BY
Try it →
Medium Free
Subquery in FROM (Derived Table)
Uses: Subquery Derived Table JOIN GROUP BY
Try it →
Medium Free
Above-Average Departments (Derived Table)
Uses: Subquery JOIN Aggregation GROUP BY
Try it →
Medium Free
Department Roster with GROUP_CONCAT
Uses: GROUP BY GROUP_CONCAT Aggregation Subquery
Try it →
Medium Free
Highest Total Salary Budget Department
Uses: GROUP BY Aggregation Subquery HAVING
Try it →
Medium Free
UNION ALL Dedup: Cross-Dataset Search
Uses: UNION ALL UNION CTE CASE
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
Active and Recently Failed
Finance & Banking track · Uses: UNION ALL WHERE Set Operations
Try it →
Medium Free
Combined Sales and Permits Activity
Real Estate track · Uses: UNION ALL Set Operations
Try it →
Medium Free
Failure Mode Catalog Join
Manufacturing & Industry track · Uses: JOIN UNION ALL Set Operations
Try it →
Hard Free preview
Running Total Revenue
Uses: Subquery Window Functions GROUP BY Aggregation
Try it →
Hard Free preview
Year-over-Year Growth
Uses: Subquery Window Functions GROUP BY Aggregation
Try it →
Hard Pro
Customer Lifetime Value Pipeline
Uses: JOIN Subquery Window Functions NTILE
Try it →
Hard Pro
Top Spender Per Country
Uses: Subquery GROUP BY HAVING Aggregation
Try it →
Hard Pro
Nth Highest Salary per Department
Uses: Subquery Window Functions WHERE Window Function
Try it →
Hard Pro
Top Earner Per Department
Uses: Window Functions Subquery
Try it →
Hard Pro
Earliest Movie per Genre
Uses: Window Functions ROW_NUMBER PARTITION BY Subquery
Try it →
The subquery is the inside-out spelling; the same problems written top-down with WITH are on the CTE page, and several Hard ones here open with WITH and appear on both. When the choice matters — and when it does not — is on CTE vs subquery vs temp table.