Subqueries


Subqueries(nested queries) are queries embedded within another SQL query. They can be used in the SELECT, FROM, WHERE, and HAVING clauses, providing flexibility for sophisticated data manipulation. Subqueries execute first, and their results are then used by the outer query.

 

Single-Row Subqueries: Returning one row, one column (used with =, !=, >, <)

A single-row subquery returns a maximum of one row and one column. These are typically used with single-row comparison operators such as =, !=, >, <, >=, and <=. If a single-row subquery returns more than one row, an error will occur.

Example 1: Oracle 19c SQL Single-Row Subquery with EQUAL operator

SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE salary = (SELECT MIN(salary) FROM employees); -- Finds the minimum salary and returns employees with that salary

Explanation This query finds employees whose salary matches the minimum salary in the employees table. The subquery determines the lowest salary, and the outer query filters based on this single value.

Example 2: Oracle 19c SQL Single-Row Subquery with GREATER THAN operator

SELECT product_id, product_name, list_price
FROM products
WHERE list_price > (SELECT AVG(list_price) FROM products); -- Retrieves products with a list price greater than the average list price

Explanation This example identifies products with a list_price higher than the average list_price of all products. The subquery calculates the average, which the outer query then uses for filtering.

Example 3: Oracle 19c SQL Single-Row Subquery with NOT EQUAL operator

SELECT department_id, department_name
FROM departments
WHERE department_id != (SELECT department_id FROM employees WHERE first_name = 'Steven' AND last_name = 'King'); -- Excludes the department where Steven King works

Explanation This query lists all departments, excluding the one where 'Steven King' works. The subquery identifies Steven King's department, which the outer query then excludes.

 

Multiple-Row Subqueries: Returning multiple rows, one column (used with IN, ANY, ALL)

Multiple-row subqueries return one or more rows, but only one column. These subqueries are typically used with multiple-row comparison operators such as IN, NOT IN, ANY, and ALL. Attempting to use a single-row operator with a multiple-row subquery will result in an error.

Example 1: Oracle 19c SQL Multiple-Row Subquery with IN operator

SELECT employee_id, first_name, last_name, department_id
FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE location_id = 1700); -- Selects employees from departments located at location_id 1700

Explanation This query retrieves employees from departments located at location_id 1700. The subquery returns a list of department IDs, and the IN operator checks for matches.

Example 2: Oracle 19c SQL Multiple-Row Subquery with ANY operator

SELECT product_id, product_name, list_price
FROM products
WHERE list_price > ANY (SELECT list_price FROM products WHERE category_id = 5); -- Finds products with a list price greater than at least one product in category_id 5

Explanation This example finds products whose list_price is greater than any list_price from products in category_id 5. The ANY operator ensures the condition is met if the price is greater than the smallest value returned by the subquery.

Example 3: Oracle 19c SQL Multiple-Row Subquery with ALL operator

SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE salary > ALL (SELECT salary FROM employees WHERE job_id = 'IT_PROG'); -- Returns employees whose salary is greater than all salaries of IT programmers

Explanation This query identifies employees whose salary is strictly greater than all salaries of 'IT_PROG' employees. The ALL operator ensures the salary must exceed the maximum value returned by the subquery.

 

Multiple-Column Subqueries: Returning multiple columns in WHERE clause

Multiple-column subqueries return more than one column in the WHERE clause of the outer query. These are particularly useful when you need to compare multiple columns simultaneously.

Example 1: Oracle 19c SQL Multiple-Column Subquery for paired comparison

SELECT employee_id, first_name, last_name, job_id, department_id
FROM employees
WHERE (job_id, department_id) IN (SELECT job_id, department_id FROM employees WHERE employee_id = 100); -- Finds employees with the same job_id and department_id as employee 100

Explanation This query finds employees with the exact same job_id and department_id as employee 100. The IN operator uses a paired column comparison.

Example 2: Oracle 19c SQL Multiple-Column Subquery with MAX values

SELECT product_id, product_name, category_id, list_price
FROM products
WHERE (category_id, list_price) IN (SELECT category_id, MAX(list_price) FROM products GROUP BY category_id); -- Finds the most expensive product in each category

Explanation This example identifies the product(s) with the highest list_price within each category_id. The subquery returns each category's max price, which the outer query matches.

Example 3: Oracle 19c SQL Multiple-Column Subquery for non-matching pairs

SELECT employee_id, first_name, last_name, manager_id, department_id
FROM employees
WHERE (manager_id, department_id) NOT IN (SELECT manager_id, department_id FROM employees WHERE salary > 15000); -- Finds employees whose manager_id and department_id pair do not exist for highly paid employees

Explanation This query retrieves employees whose manager_id and department_id combination is not found among highly paid employees. The NOT IN clause excludes specific manager-department pairs.

 

Correlated Subqueries: Subquery dependent on outer query

A correlated subquery is a subquery that depends on the outer query for its values. It executes once for each row processed by the outer query. This means the inner query cannot be executed independently of the outer query. Correlated subqueries are typically used for row-by-row processing.

Example 1: Oracle 19c SQL Correlated Subquery to find employees earning more than their department's average

SELECT e.employee_id, e.first_name, e.last_name, e.salary, e.department_id
FROM employees e
WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id); -- For each employee, compares their salary to the average salary of their own department

Explanation This query finds employees earning more than their own department's average salary. The subquery is correlated as it recalculates the average for each employee's department.

Example 2: Oracle 19c SQL Correlated Subquery to find departments with at least one employee earning above a certain salary

SELECT d.department_name
FROM departments d
WHERE EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.department_id AND e.salary > 10000); -- Checks if there's any employee in the department with salary > 10000

Explanation This example lists departments with at least one employee earning over 10000. The EXISTS operator, with the correlated subquery, checks for such an employee in each department.

Example 3: Oracle 19c SQL Correlated Subquery for finding duplicate names within a department

SELECT e1.first_name, e1.last_name, e1.department_id
FROM employees e1
WHERE (SELECT COUNT(*) FROM employees e2 WHERE e2.first_name = e1.first_name AND e2.last_name = e1.last_name AND e2.department_id = e1.department_id) > 1; -- Finds employees with non-unique first name, last name, and department combinations

Explanation This query identifies employees with duplicate first_name, last_name, and department_id combinations. The correlated subquery counts occurrences, highlighting duplicates.

 

Scalar Subqueries: Subquery returning a single value, usable in SELECT or WHERE

A scalar subquery is a subquery that always returns at most one row and one column. Because it returns a single value, it can be used in almost any place where a single expression is valid, including the SELECT list, WHERE clause, GROUP BY clause, and HAVING clause.

Example 1: Oracle 19c SQL Scalar Subquery in SELECT clause

SELECT d.department_name,
       (SELECT COUNT(e.employee_id) FROM employees e WHERE e.department_id = d.department_id) AS total_employees -- Counts employees for each department
FROM departments d;

Explanation This query lists department names with their total employee count. The scalar subquery in the SELECT list calculates the count for each department.

Example 2: Oracle 19c SQL Scalar Subquery in WHERE clause for comparison

SELECT product_id, product_name, list_price
FROM products
WHERE list_price > (SELECT MAX(list_price) * 0.8 FROM products WHERE category_id = 1); -- Finds products with a list price greater than 80% of the maximum price in category 1

Explanation This example retrieves products whose list_price is greater than 80% of the maximum price in category_id 1. The scalar subquery calculates this single threshold value for filtering.

Example 3: Oracle 19c SQL Scalar Subquery for dynamic column values

SELECT employee_id, first_name, last_name,
       (SELECT department_name FROM departments WHERE department_id = e.department_id) AS employee_department -- Retrieves the department name for each employee
FROM employees e;

Explanation This query lists employee details along with their department names. The scalar subquery in the SELECT list fetches the department_name for each employee's department.