Subqueries in FROM clause (derived tables) in MySQL - Time & Space Complexity
When using subqueries inside the FROM clause, it's important to understand how the database processes them.
We want to know how the work grows as the data size increases.
Analyze the time complexity of the following code snippet.
SELECT d.customer_id, d.total_orders
FROM (
SELECT customer_id, COUNT(*) AS total_orders
FROM orders
GROUP BY customer_id
) AS d
WHERE d.total_orders > 5;
This query counts orders per customer in a subquery, then filters customers with more than 5 orders.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Scanning all rows in the orders table to count orders per customer.
- How many times: Once over all orders, then grouping by customer to aggregate counts.
As the number of orders grows, the database must look at each order once to count them.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 row reads and counts |
| 100 | About 100 row reads and counts |
| 1000 | About 1000 row reads and counts |
Pattern observation: The work grows roughly in direct proportion to the number of orders.
Time Complexity: O(n)
This means the time to run the query grows linearly with the number of orders.
[X] Wrong: "The subquery runs multiple times for each outer row, making it slower than it really is."
[OK] Correct: The subquery in the FROM clause runs once, creating a temporary result before filtering, so it does not repeat per outer row.
Understanding how subqueries in the FROM clause work helps you explain query performance clearly and shows you know how databases process data step-by-step.
"What if we added an index on customer_id in the orders table? How would the time complexity change?"
Practice
FROM clause in MySQL?Solution
Step 1: Understand the role of subqueries in FROM clause
Subqueries in the FROM clause act like temporary tables that the outer query can use to simplify complex queries.Step 2: Differentiate from other SQL operations
Updating or deleting data is not the purpose of subqueries in FROM; they are for organizing data selection.Final Answer:
To create a temporary table that the outer query can use -> Option DQuick Check:
Subquery in FROM = temporary table [OK]
- Confusing subqueries in FROM with UPDATE or DELETE statements
- Thinking subqueries create permanent tables
- Ignoring the need for an alias for the subquery
FROM clause in MySQL?Solution
Step 1: Identify correct subquery syntax in FROM clause
The subquery must be enclosed in parentheses and given an alias usingAS.Step 2: Check each option
SELECT * FROM (SELECT id FROM users) AS sub; correctly uses parentheses and alias. Others misuse syntax or place subquery incorrectly.Final Answer:
SELECT * FROM (SELECT id FROM users) AS sub; -> Option AQuick Check:
Subquery in FROM needs parentheses + alias [OK]
- Forgetting to alias the subquery
- Placing subquery outside parentheses
- Using subquery in WHERE or FROM incorrectly
users(id, name)orders(id, user_id, amount)What will the following query return?
SELECT sub.user_id, sub.total_amount FROM (SELECT user_id, SUM(amount) AS total_amount FROM orders GROUP BY user_id) AS sub WHERE sub.total_amount > 100;
Solution
Step 1: Understand the subquery
The subquery calculates total order amount per user by grouping orders by user_id and summing amounts.Step 2: Apply the outer query filter
The outer query selects users whose total order amount is greater than 100 from the subquery result.Final Answer:
List of user IDs with total order amount greater than 100 -> Option BQuick Check:
Subquery sums orders; outer filters total_amount > 100 [OK]
- Confusing total order amount with individual order amounts
- Forgetting to alias the subquery
- Assuming syntax error without checking alias
SELECT sub.user_id, sub.total FROM (SELECT user_id, SUM(amount) FROM orders GROUP BY user_id);
Solution
Step 1: Check subquery alias requirement
Subqueries in FROM clause must have an alias; this query lacks it.Step 2: Verify other parts
SUM(amount) without alias is allowed but referencing it as sub.total will fail; aliasing subquery is mandatory.Final Answer:
Missing alias for the subquery -> Option CQuick Check:
Subquery in FROM needs alias [OK]
- Assuming SUM() must be aliased
- Thinking GROUP BY is disallowed in subqueries
- Ignoring alias requirement for subqueries
FROM clause to achieve this?Tables:
users(id, name)
orders(id, user_id, amount)
Solution
Step 1: Understand the requirement
We need users with total order amount > 500 and more than 3 orders.Step 2: Analyze each option's approach
SELECT u.name, stats.total_amount FROM users u JOIN (SELECT user_id, COUNT(*) AS order_count, SUM(amount) AS total_amount FROM orders GROUP BY user_id) AS stats ON u.id = stats.user_id WHERE stats.total_amount > 500 AND stats.order_count > 3; uses a subquery in FROM to calculate order count and total per user, then joins users to filter correctly. SELECT u.name FROM users u WHERE (SELECT SUM(amount) FROM orders WHERE user_id = u.id) > 500 AND (SELECT COUNT(*) FROM orders WHERE user_id = u.id) > 3; uses correlated subqueries but not FROM clause subquery. SELECT u.name, SUM(o.amount) FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.id HAVING SUM(o.amount) > 500 AND COUNT(o.id) > 3; uses HAVING but no subquery in FROM. SELECT name FROM users WHERE id IN (SELECT user_id FROM orders GROUP BY user_id HAVING SUM(amount) > 500 AND COUNT(*) > 3); uses IN with subquery but no join.Step 3: Confirm correct use of subquery in FROM
Only SELECT u.name, stats.total_amount FROM users u JOIN (SELECT user_id, COUNT(*) AS order_count, SUM(amount) AS total_amount FROM orders GROUP BY user_id) AS stats ON u.id = stats.user_id WHERE stats.total_amount > 500 AND stats.order_count > 3; uses a derived table (subquery in FROM) with alias and joins properly.Final Answer:
SELECT u.name, stats.total_amount FROM users u JOIN (SELECT user_id, COUNT(*) AS order_count, SUM(amount) AS total_amount FROM orders GROUP BY user_id) AS stats ON u.id = stats.user_id WHERE stats.total_amount > 500 AND stats.order_count > 3; -> Option AQuick Check:
Subquery in FROM calculates stats; outer query filters users [OK]
- Not aliasing the subquery in FROM
- Using correlated subqueries instead of derived tables
- Missing join between users and subquery results
Ready to prove it?
Pass the test and this pattern moves unknown
