Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
A subquery is a query inside another query. It lets you use an answer you do not know yet: the longest film, the average rating, the set of ids that match something. Without one you would run 2 queries and paste the first result into the second by hand. Open the client with mysql -u root -p sakila before you start.

How a subquery works

Replace COLUMN_LIST with the columns you want, TABLE_NAME with the table, COLUMN_NAME with the column to test, and AGGREGATE_FUNCTION with the function that produces the value you are comparing against. The server runs the subquery, takes its result, and uses it in the outer query. A subquery in brackets that returns exactly 1 row and 1 column is a scalar subquery, and it behaves like a value. That is the form below, and the form that goes wrong most often.

Examples

1) Use a value you cannot write down

You do not know the longest film’s length, so ask for it in place.
MAX(length) on its own would give 185 and nothing else. The subquery feeds it back into a WHERE so you get the films as well.

2) A subquery in the select list

The same value can go in the select list, where it repeats on every row.
The subquery runs once and its answer is copied down the column, which is how you show a value beside the rows you are comparing against it.

3) A subquery that returns a list

A subquery feeding IN is allowed to return many rows, because IN expects a list rather than a value.
The inner query returns the ids of everyone in film 1, and IN tests each actor against that whole list.

ERROR 1242 means the subquery returned too many rows

= compares 1 thing to 1 thing. Give it a subquery that returns 1,000 rows and the server cannot go on.
3 ways out, depending on what you meant:
  • Use IN instead of =, when a list is what you wanted.
  • Add an aggregate such as MAX(), when you wanted 1 value from the set.
  • Add LIMIT 1, when any 1 row will do and you can say which with ORDER BY.
ERROR 1242 at least fails loudly. The version of this mistake that does not is a subquery returning no rows at all: that gives NULL, the comparison gives NULL, and the outer query silently returns nothing.

Summary

  • Use a subquery to feed one query’s answer into another.
  • Expect a scalar subquery, 1 row and 1 column, to behave like a value.
  • Read ERROR 1242 as = against a subquery that returned many rows.
  • Use IN rather than = when the subquery returns a list.
  • Suspect an empty subquery when an outer query returns nothing and no error.

See also