A subquery is a query nested within another query. Subqueries can be used in SELECT
, INSERT
, UPDATE
, or DELETE
statements or within clauses like WHERE
, FROM
, or HAVING
. They help simplify complex SQL queries by breaking them into smaller parts.
Syntax
SELECT column_names
FROM table_name
WHERE column_name = (SELECT column_names FROM another_table WHERE condition);
Types of Subqueries
- Single-row Subquery: Returns a single row.
- Multi-row Subquery: Returns multiple rows.
- Correlated Subquery: Refers to columns in the outer query.
- Nested Subquery: A subquery within another subquery.
Example 1: Single-row Subquery
Goal: Find the customer who placed the earliest order.
Query
SELECT CustomerID, OrderDate
FROM Orders
WHERE OrderDate = (
SELECT MIN(OrderDate)
FROM Orders
);
Explanation
- The subquery finds the earliest
OrderDate
from theOrders
table. - The outer query retrieves the
CustomerID
andOrderDate
for that earliest order.
Example 2: Multi-row Subquery
Goal: List all products that have been ordered.
Query
SELECT ProductName
FROM Products
WHERE ProductID IN (
SELECT ProductID
FROM OrderDetails
);
Explanation
- The subquery selects all
ProductID
s fromOrderDetails
(products that have been ordered). - The outer query retrieves the
ProductName
for theseProductID
s from theProducts
table.
Example 3: Correlated Subquery
Goal: Find employees who have placed orders.
Query
SELECT EmployeeID, LastName
FROM Employees e
WHERE EXISTS (
SELECT 1
FROM Orders o
WHERE o.EmployeeID = e.EmployeeID
);
Explanation
- The subquery checks if there are orders in the
Orders
table for eachEmployeeID
from theEmployees
table. - The outer query retrieves employees who match the condition.
Example 4: Subquery in the FROM
Clause
Goal: Find the total number of orders placed by each customer.
Query
SELECT CustomerID, TotalOrders
FROM (
SELECT CustomerID, COUNT(OrderID) AS TotalOrders
FROM Orders
GROUP BY CustomerID
) AS CustomerOrders
WHERE TotalOrders > 5;
Explanation
- The inner query calculates the total number of orders (
TotalOrders
) for each customer. - The outer query filters customers who have placed more than 5 orders.
Example 5: Subquery in the SELECT
Clause
Goal: Retrieve all orders and include the total amount for each order.
Query
SELECT OrderID,
(SELECT SUM(Quantity * UnitPrice)
FROM OrderDetails
WHERE OrderDetails.OrderID = Orders.OrderID) AS TotalAmount
FROM Orders;
Explanation
- The subquery calculates the total amount for each order by summing
Quantity * UnitPrice
in theOrderDetails
table. - The outer query displays the
OrderID
and its correspondingTotalAmount
.
Example 6: Subquery in the HAVING
Clause
Goal: List categories with total sales greater than the average category sales.
Query
SELECT c.CategoryID, c.CategoryName, SUM(od.Quantity * od.UnitPrice) AS TotalSales
FROM Categories c
JOIN Products p ON c.CategoryID = p.CategoryID
JOIN OrderDetails od ON p.ProductID = od.ProductID
GROUP BY c.CategoryID, c.CategoryName
HAVING TotalSales > (
SELECT AVG(TotalSales)
FROM (
SELECT SUM(od.Quantity * od.UnitPrice) AS TotalSales
FROM Categories c
JOIN Products p ON c.CategoryID = p.CategoryID
JOIN OrderDetails od ON p.ProductID = od.ProductID
GROUP BY c.CategoryID
) AS CategorySales
);
Explanation
- The inner subquery calculates the average sales per category.
- The outer query lists categories whose total sales exceed the average.
When to Use Subqueries
- Simplify complex logic: Break down tasks into smaller, more manageable queries.
- Filter data dynamically: Use correlated subqueries for dynamic filtering.
- Aggregate results: Nest subqueries to compute aggregate data.
Key Points
- Performance: Subqueries can be less efficient than joins, especially for large datasets. Optimize queries or replace subqueries with joins if possible.
- Correlated Subqueries: These are slower since they execute once for each row in the outer query.
- Nested Subqueries: Can become hard to read. Use clear alias names for readability.