📖 Scenario: You are managing a small online bookstore database. You want to find books that have a price higher than the average price of books in the same category.
🎯 Goal: Build a MySQL query using a correlated subquery to list all books with prices above the average price of their category.
📋 What You'll Learn
Create a table called books with columns id, title, category, and price.
Insert the exact data rows provided into the books table.
Write a correlated subquery that calculates the average price per category.
Select books where the price is greater than the average price of their category.
💡 Why This Matters
🌍 Real World
Correlated subqueries help compare each row to a group of related rows, useful in sales, inventory, and reporting databases.
💼 Career
Understanding correlated subqueries is important for database analysts and developers to write efficient and meaningful queries.
Progress0 / 4 steps
1
Create the books table and insert data
Create a table called books with columns id as INT, title as VARCHAR(100), category as VARCHAR(50), and price as DECIMAL(5,2). Then insert these exact rows: (1, 'Learn SQL', 'Programming', 25.00), (2, 'Advanced SQL', 'Programming', 40.00), (3, 'Cooking 101', 'Cooking', 15.00), (4, 'Baking Basics', 'Cooking', 20.00), (5, 'Gardening Tips', 'Gardening', 30.00).
MySQL
Hint
Use CREATE TABLE to define the table and INSERT INTO to add rows.
2
Write the correlated subquery to find average price per category
Write a SELECT statement that uses a correlated subquery to calculate the average price of books in the same category as each book. Use the alias b for the outer query and b2 for the subquery.
MySQL
Hint
Use a subquery inside the SELECT clause that refers to the outer query's b.category.
3
Filter books with price above average category price
Modify the previous SELECT query to include a WHERE clause that selects only books where b.price is greater than the average price of their category using the correlated subquery.
MySQL
Hint
Use the correlated subquery inside the WHERE clause to compare prices.
4
Complete the query with ordering by category and price
Add an ORDER BY clause to the query to sort the results first by category ascending and then by price descending.
MySQL
Hint
Use ORDER BY with multiple columns separated by commas.
Practice
(1/5)
1. What is a correlated subquery in MySQL?
easy
A. A subquery that uses values from the outer query for each row.
B. A subquery that runs only once before the outer query.
C. A query that joins two tables without any subqueries.
D. A subquery that returns a fixed constant value.
Solution
Step 1: Understand subquery behavior
A correlated subquery depends on the outer query's current row values to execute.
Step 2: Compare options
The option describing a subquery that uses values from the outer query for each row correctly defines a correlated subquery.
Final Answer:
A subquery that uses values from the outer query for each row. -> Option A
Quick Check:
Correlated subquery = uses outer row values [OK]
Hint: Correlated subqueries depend on outer query row values [OK]
Common Mistakes:
Thinking subqueries always run once
Confusing joins with subqueries
Assuming subqueries return constants only
2. Which of the following is the correct syntax for a correlated subquery in MySQL?
easy
A. SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = employees.department_id);
B. SELECT * FROM employees WHERE salary IN (SELECT salary FROM employees);
C. SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
D. SELECT * FROM employees WHERE salary = 50000;
Solution
Step 1: Identify correlated subquery syntax
A correlated subquery references a column from the outer query inside the subquery, like e2.department_id = employees.department_id.
Step 2: Check each option
SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = employees.department_id); uses the outer table's column inside the subquery condition, making it a correlated subquery.
Final Answer:
SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = employees.department_id); -> Option A
Quick Check:
Correlated subquery syntax = SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = employees.department_id); [OK]
Hint: Look for subquery referencing outer query table alias [OK]
Common Mistakes:
Missing outer table reference in subquery
Using subquery without WHERE clause for correlation
Confusing correlated with simple subqueries
3. Given the tables: employees(id, name, department_id, salary) and departments(id, name) What will this query return?
SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id);
medium
A. Employees whose salary is above the average salary of all departments combined.
B. Employees whose salary is above the average salary of all employees.
C. Employees whose salary is above the average salary of their department.
D. Syntax error due to subquery referencing outer query.
Solution
Step 1: Understand the subquery condition
The subquery calculates the average salary for the department of the current employee (using e.department_id).
Step 2: Compare employee salary with department average
The outer query selects employees whose salary is greater than their department's average salary.
Final Answer:
Employees whose salary is above the average salary of their department. -> Option C
Quick Check:
Correlated subquery filters by department average salary [OK]
Hint: Check if subquery filters by outer row's department_id [OK]
Common Mistakes:
Thinking subquery calculates overall average salary
Assuming syntax error due to correlation
Confusing department and employee averages
4. Identify the error in this correlated subquery:
SELECT e1.name FROM employees e1 WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.department = e1.department_id);
medium
A. Subquery cannot reference outer query columns.
B. Alias 'e1' is not allowed in subquery.
C. Missing GROUP BY clause in subquery.
D. Column 'department' does not exist in employees table.
Solution
Step 1: Check column names in subquery condition
The subquery compares e2.department to e1.department_id, but 'department' column does not exist in employees table.
Step 2: Confirm correct column usage
The correct column should be e2.department_id to match e1.department_id for correlation.
Final Answer:
Column 'department' does not exist in employees table. -> Option D
Quick Check:
Invalid column name causes error [OK]
Hint: Verify column names match exactly in both queries [OK]
Common Mistakes:
Using wrong column names for correlation
Assuming alias usage causes error
Thinking GROUP BY is required in subquery
5. You want to find all departments where every employee earns more than the average salary of all employees in the company. Which query correctly uses a correlated subquery to achieve this?
hard
A. SELECT d.name FROM departments d WHERE ALL (SELECT salary FROM employees WHERE department_id = d.id) > (SELECT AVG(salary) FROM employees);
B. SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.salary <= (SELECT AVG(salary) FROM employees));
C. SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.salary > (SELECT AVG(salary) FROM employees));
D. SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.salary > (SELECT AVG(salary) FROM employees WHERE department_id = d.id));
Solution
Step 1: Understand the requirement
We want departments where every employee earns more than the company-wide average salary.
Step 2: Analyze the NOT EXISTS query
SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.salary <= (SELECT AVG(salary) FROM employees)); uses NOT EXISTS to ensure no employee in the department earns less or equal to the company average, meaning all earn more.
Step 3: Check other options
The options using EXISTS check for the existence of at least one qualifying employee, not all. The option attempting to use ALL with a subquery on the left side uses invalid syntax in MySQL.
Final Answer:
SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id AND e.salary <= (SELECT AVG(salary) FROM employees)); -> Option B
Quick Check:
NOT EXISTS ensures all employees earn above average [OK]
Hint: Use NOT EXISTS to check all employees meet condition [OK]
Common Mistakes:
Using EXISTS instead of NOT EXISTS for 'all' condition
Misusing ALL keyword in MySQL
Comparing with department average instead of company average
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.