Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. SQL Dictionary
  3. Subqueries (Scalar and Row)

Subqueries (Scalar and Row)

Since: SQL-92(1992)

A subquery is a SELECT statement embedded inside another query. A scalar subquery always returns a single value (one column, one row), while a row subquery returns one row with multiple columns.

Syntax

Scalar subquery: embedded as a single value in a SELECT list, WHERE condition, SET clause, etc.

SELECT column_name, (SELECT aggregate_function(...) FROM ...) AS alias
FROM table;

Using a scalar subquery in a WHERE clause.

SELECT column_name
FROM table
WHERE column_name = (SELECT statement that returns a single value);

Row subquery: compares multiple columns at once.

SELECT column_name
FROM table
WHERE (column_a, column_b) = (SELECT column_a, column_b FROM ... LIMIT 1);

Syntax Overview

TypeDescription
Scalar subqueryA subquery that returns a single value (one column, one row). Can be used in SELECT lists, WHERE clauses, SET clauses, and more.
Row subqueryA subquery that returns one row with multiple columns. Used with row value expressions to compare multiple columns at once.

Sample Code

The following employees table is used in the examples below.

employees name salary department user_a 480000 Sales user_c 620000 Engineering user_e 390000 Engineering user_b 320000 Sales 4 rows in set

Display each employee's salary alongside the average salary of all employees (scalar subquery).

sample_subquery_scalar.sql
SELECT
    name,
    salary,
    (SELECT AVG(salary) FROM employees) AS avg_salary,
    salary - (SELECT AVG(salary) FROM employees) AS diff_from_avg
FROM employees
ORDER BY salary DESC;
+--------+--------+------------+---------------+
| name   | salary | avg_salary | diff_from_avg |
+--------+--------+------------+---------------+
| user_c | 620000 | 452500.0000 |   167500.0000 |
| user_a | 480000 | 452500.0000 |    27500.0000 |
| user_e | 390000 | 452500.0000 |   -62500.0000 |
| user_b | 320000 | 452500.0000 |  -132500.0000 |
+--------+--------+------------+---------------+
4 rows in set

Retrieve the employee with the highest salary.

sample_subquery_scalar.sql
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
+--------+--------+
| name   | salary |
+--------+--------+
| user_c | 620000 |
+--------+--------+
1 row in set

Use a row subquery to find employees with the same salary and department as the highest-paid employee.

sample_subquery_scalar.sql
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
    SELECT salary, department
    FROM employees
    ORDER BY salary DESC
    LIMIT 1
);
+--------+--------+------------+
| name   | salary | department |
+--------+--------+------------+
| user_c | 620000 | Engineering  |
+--------+--------+------------+
1 row in set

Database-Specific Syntax

Scalar subquery syntax is supported consistently across all major databases.

-- MySQL, PostgreSQL, SQL Server, Oracle, SQLite (all compatible)
SELECT name, salary, (SELECT AVG(salary) FROM employees) AS avg_salary
FROM employees
ORDER BY salary DESC;

The syntax for limiting a row subquery to one row differs by database. MySQL, PostgreSQL, and SQLite use LIMIT 1.

-- MySQL, PostgreSQL, SQLite
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
    SELECT salary, department FROM employees ORDER BY salary DESC LIMIT 1
);

Oracle uses FETCH FIRST 1 ROW ONLY (version 12c and later). For earlier versions, use ROWNUM to limit the result.

-- Oracle (12c and later)
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
    SELECT salary, department FROM employees ORDER BY salary DESC
    FETCH FIRST 1 ROW ONLY
);

SQL Server uses TOP 1. Note that SQL Server does not support row subqueries (comparing multiple columns simultaneously), so you must compare each column using a separate subquery.

-- SQL Server (row subqueries not supported; compare each column separately)
SELECT name, salary, department
FROM employees
WHERE salary = (SELECT TOP 1 salary FROM employees ORDER BY salary DESC)
  AND department = (SELECT TOP 1 department FROM employees ORDER BY salary DESC);

Notes

A scalar subquery must return exactly one column and one row. Returning two or more rows causes a runtime error. Aggregate functions (MAX, MIN, AVG, COUNT) naturally produce a single row, making them a natural fit for scalar subqueries.

Scalar subqueries can be used in many clauses: SELECT, WHERE, HAVING, and SET (in UPDATE statements). When placed in a SELECT clause, the subquery is evaluated for every row in the result, which can be slow on large datasets — consider rewriting with a JOIN or derived table in that case.

To compare against subqueries that return multiple rows, use IN / EXISTS or ALL / ANY. For subqueries that reference the outer query, see Correlated Subqueries.

If you find any errors or copyright issues, please .