Documentation Home
MySQL 5.5 Reference Manual
Related Documentation Download this Manual Excerpts from this Manual

13.2.10 Subquery Syntax

A subquery is a SELECT statement within another statement.

All subquery forms and operations that the SQL standard requires are supported, as well as a few features that are MySQL-specific.

Here is an example of a subquery:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

In this example, SELECT * FROM t1 ... is the outer query (or outer statement), and (SELECT column1 FROM t2) is the subquery. We say that the subquery is nested within the outer query, and in fact it is possible to nest subqueries within other subqueries, to a considerable depth. A subquery must always appear within parentheses.

The main advantages of subqueries are:

  • They allow queries that are structured so that it is possible to isolate each part of a statement.

  • They provide alternative ways to perform operations that would otherwise require complex joins and unions.

  • Many people find subqueries more readable than complex joins or unions. Indeed, it was the innovation of subqueries that gave people the original idea of calling the early SQL Structured Query Language.

Here is an example statement that shows the major points about subquery syntax as specified by the SQL standard and supported in MySQL:

 (SELECT COUNT(*) /* no hint */ FROM t2
   (SELECT * FROM t3
    WHERE ROW(5*t2.s1,77)=
     (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
      (SELECT * FROM t5) AS t5)));

A subquery can return a scalar (a single value), a single row, a single column, or a table (one or more rows of one or more columns). These are called scalar, column, row, and table subqueries. Subqueries that return a particular kind of result often can be used only in certain contexts, as described in the following sections.

There are few restrictions on the type of statements in which subqueries can be used. A subquery can contain many of the keywords or clauses that an ordinary SELECT can contain: DISTINCT, GROUP BY, ORDER BY, LIMIT, joins, index hints, UNION constructs, comments, functions, and so on.

A subquery's outer statement can be any one of: SELECT, INSERT, UPDATE, DELETE, SET, or DO.

In MySQL, you cannot modify a table and select from the same table in a subquery. This applies to statements such as DELETE, INSERT, REPLACE, UPDATE, and (because subqueries can be used in the SET clause) LOAD DATA INFILE.

For information about how the optimizer handles subqueries, see Section, “Optimizing Subqueries with EXISTS Strategy”. For a discussion of restrictions on subquery use, including performance issues for certain forms of subquery syntax, see Section C.4, “Restrictions on Subqueries”.

Download this Manual
User Comments
  Posted by Are you mortal Then prepare to die. on January 5, 2005

Ever wanted to turn an AUTO_INCRIMENT primary key into one of those 'rolling ID' columns? i.e. the type which changes back to ID = 1 when some other part of your (new) PK changes... Use a subquery!

Suppose you have this

TABLE t1...

1 <-> A
2 <-> A
3 <-> A
4 <-> B
5 <-> B
6 <-> B
7 <-> C
8 <-> C
9 <-> D

Try this cool sub-query!


) AS b

Which gives you

TABLE t2 ...

ID <-> X
1 <-> A
2 <-> A
3 <-> A
1 <-> B
2 <-> B
3 <-> B
1 <-> C
2 <-> C
1 <-> D

Cool eh?

  Posted by Tayfun Duran on September 10, 2005
If you can't use subquery, you can use this;

$sec1 = mysql_query("SELECT foto FROM profoto WHERE proje=$id");
if ($kyt1 = mysql_fetch_array($sec1)) {$dizi = $kyt1["foto"];} else {$dizi="0";}
while ($kyt1 = mysql_fetch_array($sec1)) {
$dizi = $dizi . "," . $kyt1["foto"];
$sec = mysql_query("SELECT, foto.dosya, foto.baslik FROM foto WHERE id NOT IN (" . $dizi . ") LIMIT $baslangic, $sayfalama");

First, you create a selection and then you use it in your real selection. This is a kind of subquery :)

  Posted by Svavar Lúthersson on June 4, 2006
This order of things also works for count functions. For example:

SELECT *,(SELECT COUNT(*) FROM table2 WHERE table2.field1 = AS count FROM table1 WHERE table1.field1 = 'value'

This command will enable you to count fields in table2 based on a column value in table1 and label the result as "count". The value in table1.field1 can be any valid field type.
  Posted by ch4dwick m. on May 21, 2007
Here's simple insert query I came up with that serves 3 functions in my PHP applications:
1.) retrieves data from the select query
2.) Inserts that row into another table (for record keeping purposes such as purchase orders from shopping carts)
3.) validates the input (using mysql_affected_rows()) and will return 0 if the select failed and will not insert at all.

INSERT INTO table2 (field1, field2, field3, field4) (SELECT 'value1 from user input', field1, field2, field3 from table1)

The 4 fields in table2 will be populated by the 4 fields (including the string) returned by the SELECT sub-query respectively.

I know this MIGHT raise issues with speed of queries but it's better than writing long lines of PHP code that does those 3 things - even with a framework! I can just use the mysql_affected_rows() after that query to see if everything went fine.

NOTE: Make sure the number of fields in the SELECT query is EXACTLY the same number of fields you are about to insert.
  Posted by Andy Leon on June 23, 2009
It mentions here that you cannot select from and modify the same table as part of your subquery. There is a workaround listed on the following page:

that shows you how to use a temporary table. But you can also create a View based on a table, use that for the SELECT statement and then use the regular table name for the UPDATE / DELETE statement.
  Posted by Christian Berrigan on March 14, 2010
Updating a table using a subquery. This uses an example of a table of people, and a separate table of votes those people have received. After the votes table has been populated with new votes, the total vote count of each of the people is calculated and updated with one query.

UPDATE people,
(SELECT count(*) as votecount, person_id
FROM votes GROUP BY person_id) as tally
SET people.votecount = tally.votecount
WHERE people.person_id = tally.person_id

  Posted by Devang Modi on August 30, 2011
Combine queries for Insert and Select always obeys Innodb locking rules
if one of the source table is based on Innodb engine.
It is also possible that the INSERT activity applicable to TEMPORARY
table which is not InnoDB engine. It is also possible that in SELECT
section with INNODB, some other TEMPORARY Tables are used.
Devang Modi
Sign Up Login You must be logged in to post a comment.