Subqueries: Basics & Result Types
What a subquery is, how it runs inside-out, the three result types (scalar, list, table) and subqueries in FROM and SELECT.
Question: "Which players scored more than the average?" You cannot write WHERE runs > AVG(runs) — aggregates are not allowed in WHERE. You first need the average, then the filter. A subquery lets you do both in one statement.
Definition
A subquery (also called an inner query or nested query) is a complete
SELECTstatement written inside brackets within another SQL statement (the outer query or main query). The inner query produces a result that the outer query then uses as a value, a list, or a table.
- Complete SELECT — it has its own
SELECT … FROM …and could often run alone. - Inside brackets — the brackets
( )are mandatory. - Outer query uses its result — the outer query treats it like a number, a list or a temporary table, depending on what the inner query returns.
How a subquery works — inside out
sql
SELECT name, runs
FROM players
WHERE runs > (SELECT AVG(runs) FROM players);| Step | What happens |
|---|---|
| 1. Run the inner query | SELECT AVG(runs) FROM players → 528 |
| 2. Pass the result | The value 528 is handed to the outer query |
| 3. Run the outer query | WHERE runs > 528 keeps 3 rows |
| name | runs |
|---|---|
| Virat Kohli | 750 |
| Jos Buttler | 850 |
| David Warner | 700 |
The inner query is finished before the outer query uses it (for a normal, non-correlated subquery).
Note: In SQL Server,
AVGof anINTcolumn returns an integer (528). The playground (SQLite) shows 528.33. The filtered rows are the same either way. UseAVG(runs * 1.0)in SQL Server if you need decimals.
Subquery result types
What the inner query returns decides where it is allowed to go.
| Type | Shape | Example | Where it can go |
|---|---|---|---|
| Scalar | ONE value (1 row × 1 column) | (SELECT AVG(runs) FROM players) | SELECT list, WHERE with = <> > >= < <= |
| Row / List | ONE column, many rows | (SELECT id FROM orange_cap) | WHERE … IN / NOT IN / ANY / ALL |
| Table | Many rows and many columns | (SELECT team, SUM(runs) … ) AS t | FROM / JOIN (needs an alias) |
Syntax — the three places a subquery can live
sql
-- 1. In SELECT (must be scalar)
SELECT column_name, (SELECT aggregate FROM table_b) AS alias
FROM table_a;
-- 2. In FROM (a table result — alias required)
SELECT *
FROM (SELECT ... FROM table_a) AS derived_alias;
-- 3. In WHERE (scalar with a comparison, or a list with IN / ANY / ALL / EXISTS)
SELECT *
FROM table_a
WHERE column_name > (SELECT ... FROM table_b);Example — subquery in the FROM clause (derived table)
Find teams whose total runs are 700 or more.
sql
SELECT *
FROM (
SELECT team, SUM(runs) AS total
FROM players
GROUP BY team
) AS t
WHERE total >= 700;| team | total |
|---|---|
| DC | 700 |
| RCB | 750 |
| RR | 850 |
How it works: the inner query builds a temporary result (one row per team with its total). The outer query treats that result as a table named t and filters it. A subquery in FROM is called a derived table, and in SQL Server it must have an alias (AS t).
Tip: Here you could also write
HAVING SUM(runs) >= 700. Derived tables become essential when you need to filter or join on a result that already has aggregates or window functions in it.
Example — subquery in the SELECT clause
Show every player next to the overall average.
sql
SELECT
id,
name,
runs,
(SELECT ROUND(AVG(runs), 0) FROM players) AS avg_runs
FROM players;| id | name | runs | avg_runs |
|---|---|---|---|
| 1 | Virat Kohli | 750 | 528 |
| 2 | Rohit Sharma | 500 | 528 |
| 3 | Jos Buttler | 850 | 528 |
| 4 | MS Dhoni | 350 | 528 |
| 5 | David Warner | 700 | 528 |
| 6 | Jasprit Bumrah | 20 | 528 |
How it works: the inner query returns one value (a scalar), and that same value is repeated on every row. A subquery in SELECT must return a single value — otherwise SQL Server raises an error.
Common mistakes
- ❌
WHERE runs > AVG(runs)→ aggregates are not allowed inWHERE. ✅WHERE runs > (SELECT AVG(runs) FROM players). - ❌
SELECT * FROM (SELECT team, SUM(runs) AS total FROM players GROUP BY team)→ no alias. ✅ addAS tafter the closing bracket. - ❌ A derived-table column with no name, e.g.
SUM(runs)withoutAS total→ SQL Server error "No column name was specified". ✅ alias every calculated column. - ❌ A scalar subquery that returns several rows, e.g.
WHERE runs = (SELECT runs FROM players WHERE team = 'MI')→ SQL Server error "Subquery returned more than 1 value". ✅ useIN, or make the inner query return one value (MAX,MIN,TOP 1). - ❌
ORDER BYinside a subquery → not allowed in SQL Server unlessTOPis also used. ✅ sort in the outer query.
Note: SQLite (the playground) silently uses the first row when a scalar subquery returns many rows. SQL Server is stricter and raises an error — always write it the strict way.
Interview tip
Q: What is the difference between a subquery in FROM and a subquery in WHERE?
A subquery in FROM returns a table (a derived table) that the outer query reads rows from, and it needs an alias. A subquery in WHERE returns a value or a list that the outer query compares against to decide which rows to keep.
Key points to remember
- A subquery is a complete SELECT inside brackets, used by an outer (main) query.
- A normal subquery runs first (inside out) and hands its result to the outer query.
- Scalar = one value; List = one column of many rows; Table = many rows and columns.
- A subquery in SELECT must be scalar — its single value repeats on every row.
- A subquery in FROM is a derived table and must have an alias in SQL Server.
- Aggregates cannot go directly in WHERE — compare against a scalar subquery instead.
- SQL Server raises an error if a scalar subquery returns more than one row.
Try it yourself
Above-average players (scalar subquery in WHERE)
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Derived table in FROM
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Scalar subquery in SELECT
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Practice: below-average players
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Revision Flashcards
Tap a card to flip it and see the answer.
