Lesson 10 of 10 · 9 min · 2 hands-on steps
Subqueries & CTEs
Use the answer of one query inside another, and keep complex queries readable.
A query inside a query
SELECT name, salary FROM employees WHERE salary = (SELECT MAX(salary) FROM employees);
The inner query runs first and returns one value (the max salary). The outer query uses it.
Subqueries can also return a list:
SELECT name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE quantity >= 2);
CTEs: name your steps
A common table expression (WITH) lets you build a complex query step by step, like variables in code:
WITH dept_avg AS ( SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id ) SELECT e.name, e.salary, ROUND(d.avg_salary) AS dept_average FROM employees e JOIN dept_avg d ON d.department_id = e.department_id WHERE e.salary > d.avg_salary;
That finds people paid above their own department's average. Try writing it without the CTE and you'll see why professionals love them.
🎯 You can now answer most SQL interview questions: filtering, grouping, joining, ranking and subqueries. Practice them in Interview Prep → SQL.
🧪 Practice: 2 steps
0 / 2 doneStep 1 of 2 · Above average
Return the name and salary of employees who earn more than the average salary of all employees, highest first.
SELECT AVG(salary) FROM employees;
Output appears here. Press Run or Ctrl/⌘ + Enter.
Step 2 of 2 · Revenue per customer (CTE)
Using a WITH clause, calculate each order's revenue (quantity * price), then return each customer name with their total revenue (rounded to 2 decimals), highest first.
WITH order_revenue AS ( SELECT o.customer_id, o.quantity * p.price AS revenue FROM orders o JOIN products p ON p.id = o.product_id ) SELECT * FROM order_revenue;
Output appears here. Press Run or Ctrl/⌘ + Enter.
✅ Check your understanding
What is a CTE (WITH clause) mostly used for?
Create a free account to track your progress.