Skip to content
Laviyx Learn

Try

SQL course menu

Intermediate SQL Interview Questions and Answers

Intermediate SQL interview questions with worked answers: correlated subqueries, EXISTS vs IN, UNION vs UNION ALL, CASE, conditional aggregation, CTEs, views, indexes, and common query patterns.

Intermediate9 min readUpdated
On this page

These questions are typical for data analyst, BI, and backend developer interviews once the basics are covered. They test whether you can combine ideas: grouping with joins, subqueries with filters, and knowing which tool fits which problem.

The examples use the course's sample tables: employees, customers, orders and monthly_sales. See SQL Database Basics for their contents.

Concepts#

1. What is a correlated subquery?#

Show solution

A subquery that refers to a column of the outer query, so it is evaluated once per outer row. Example: employees who earn more than their own department's average:

SQLRun
SELECT name, department, salary
FROM employees e
WHERE salary > (
  SELECT AVG(salary)
  FROM employees e2
  WHERE e2.department = e.department
);
Output
name  | department  | salary
------+-------------+-------
Meera | Engineering | 81000
Priya | Sales       | 61000

See Subqueries.

2. EXISTS vs IN: what is the difference?#

Show solution

Both filter rows based on another query. IN compares a value with a list; EXISTS checks whether a correlated subquery returns any row. The important practical difference is with negation: NOT IN returns no rows if the subquery yields a NULL, while NOT EXISTS is unaffected. Modern optimisers often execute IN and EXISTS similarly. See EXISTS and IN.

3. UNION vs UNION ALL?#

Show solution

Both stack the results of queries with the same number of columns. UNION removes duplicate rows, which requires extra work; UNION ALL keeps every row and is faster. Use UNION ALL unless you specifically need de-duplication, and always when the result will be counted or summed. See UNION ALL.

4. What is a CTE and why use one?#

Show solution

A Common Table Expression (WITH name AS (...)) is a named, temporary result used within one statement. It makes multi-step queries readable top to bottom, can be referenced more than once, and can be recursive for hierarchies. See CTEs.

5. What is a view? Does it improve performance?#

Show solution

A view is a saved query that can be queried like a table. It simplifies complex logic, standardises definitions, and can hide sensitive columns. A normal view does not store data or make queries faster; it re-runs its query every time. A materialized view stores the result and must be refreshed. See Views.

6. What is an index, and what is the trade-off?#

Show solution

An index is a sorted structure (usually a B-tree) that lets the database find rows without scanning the whole table. It speeds up filters, joins and sorts on the indexed columns, but slows down inserts, updates and deletes, and uses storage. Composite indexes are used from the leftmost column. See Indexes.

Queries#

7. List every customer with their number of orders, including customers with none.#

Show hint

LEFT JOIN from customers, and count a column from orders, not *.

Show solution
SQLRun
SELECT c.name, COUNT(o.order_id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name
ORDER BY orders DESC, c.name;
Output
name  | orders
------+-------
Asha  | 2
Ravi  | 1
John  | 0
Meera | 0

COUNT(*) would report 1 for John and Meera, because the left join still produces a row for them.

8. Find customers who have not ordered since 1 February 2026.#

Show solution
SQLRun
SELECT c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
    AND o.order_date >= '2026-02-01'
);
Output
name
-----
Meera
John

Asha (order on 11 February) and Ravi (20 February) are excluded. This "inactive customers" pattern is common in retention analysis.

9. Show monthly revenue by region as columns (a pivot).#

Show hint

Conditional aggregation: SUM(CASE WHEN region = 'North' THEN revenue ELSE 0 END).

Show solution
SQLRun
SELECT month,
       SUM(CASE WHEN region = 'North' THEN revenue ELSE 0 END) AS north,
       SUM(CASE WHEN region = 'South' THEN revenue ELSE 0 END) AS south
FROM monthly_sales
GROUP BY month
ORDER BY month;
Output
month   | north | south
--------+-------+------
2026-01 | 120   | 90
2026-02 | 150   | 90
2026-03 | 110   | 130
2026-04 | 170   | 125

See CASE.

10. Find the most expensive product in each category.#

Show solution

With a correlated subquery:

SQLRun
SELECT p.category, p.name, p.price
FROM products p
WHERE p.price = (
  SELECT MAX(p2.price)
  FROM products p2
  WHERE p2.category = p.category
)
ORDER BY p.category;
Output
category    | name       | price
------------+------------+------
Electronics | Laptop     | 55000
Furniture   | Desk Chair | 7000
Stationery  | Notebook   | 60

Be ready to also write it with ROW_NUMBER() or RANK() (see Advanced SQL Questions), and to explain that this version returns every product tied for the top price.

11. Revenue and order count per customer city, including cities with no orders.#

Show solution
SQLRun
SELECT c.city,
       COUNT(o.order_id)          AS orders,
       COALESCE(SUM(o.amount), 0) AS revenue
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.city
ORDER BY revenue DESC, c.city;
Output
city    | orders | revenue
--------+--------+--------
Delhi   | 1      | 560
Mumbai  | 2      | 370
Chennai | 0      | 0
Pune    | 0      | 0

12. How many distinct customers ordered each month?#

Show solution
SQLRun
-- SQLite; use DATE_TRUNC('month', order_date) in PostgreSQL
SELECT strftime('%Y-%m', order_date) AS month,
       COUNT(DISTINCT customer_id) AS active_customers
FROM orders
GROUP BY month
ORDER BY month;
Output
month   | active_customers
--------+-----------------
2026-01 | 1
2026-02 | 2
2026-03 | 1

COUNT(DISTINCT ...) matters: a customer with two orders in a month is still one active customer.

Tips#

  • When you write a join, say what one row of the result represents ("one row per order").
  • After any join followed by SUM, check for fan-out (rows multiplied by a one-to-many join). See Multiple JOINs.
  • Offer a second approach (subquery vs window function vs join). Interviewers love candidates who know trade-offs.

Next: Advanced SQL Questions.

Finished this lesson?