The discussion to this point has been of scalar or column subqueries; that is, subqueries that return a single value or a column of values. A row subquery is a subquery variant that returns a single row and can thus return more than one column value. Legal operators for row subquery comparisons are:
= > < >= <= <> != <=>
Here are two examples:
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2); SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
The queries here are both TRUE
if table
t2
has a row where column1 =
1
and column2 = 2
.
The expressions (1,2)
and
ROW(1,2)
are sometimes called row
constructors. The two are equivalent. The row
constructor and the row returned by the subquery must contain
the same number of values.
In MySQL 5.1, a row constructor is used for
comparisons with subqueries that return two or more columns.
When a subquery returns a single column, this is regarded as a
scalar value and not as a row; a row constructor cannot be used
with a subquery that does not return at least two columns. Thus,
a query such as SELECT * FROM t1 WHERE ROW(1) = (SELECT
column1 FROM t2)
fails with a syntax error.
Row constructors are legal in other contexts. For example, the following two statements are semantically equivalent:
SELECT * FROM t1 WHERE (column1,column2) = (1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
Prior to MySQL 5.1.12, only the second of the preceding two expressions could be optimized. (Bug#16081)
The following query answers the request, “find all rows in
table t1
that also exist in table
t2
”:
SELECT column1,column2,column3 FROM t1 WHERE (column1,column2,column3) IN (SELECT column1,column2,column3 FROM t2);
User Comments
Here is a query which can be useful in data analysis. Suppose I have two tables, each with a multipart primary key. I wanted to find out on average how common it is for the two tables to have a primary key in common (this is quite silly, as you can easily count the totals, and analytically solve the problem with probability, but it serves as a demonstration of the query, and also lets you estimate varience, which might be tricky to calculate).
If you try the following you will find it fails in mysql version 4.1,
SELECT
COUNT(*)
FROM
TABLE_1
WHERE
ROW (PK_PART_1, PK_PART_2) IN
(
SELECT
PK_PART_1, PK_PART_2
FROM
TABLE_2
LIMIT
10 -- This is the basis of the whole idea
)
AND
Whatever;
The above fails with the warning ...
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
However, you can get the desired behaviour with a slight rewrite...
SELECT
COUNT(*)
FROM
TABLE_1
INNER JOIN
(
SELECT
PK_PART_1, PK_PART_2
FROM
TABLE_2
LIMIT
10 -- HEY HEY!
) AS VIRTUAL_TABLE_2
ON
TABLE_1.PK_PART_1 = TABLE_2.PK_PART_1 AND
TABLE_1.PK_PART_2 = TABLE_2.PK_PART_2
WHERE
Whatever;
And it works like a charm!
Now just add a 'ORDER BY RAND()' to the inner query, and your sampler is in action. Not much use, but illustrates an example.
Shame SQL dosn't get any decent display markup in the user comments. My highly refined layout format is wasted on this site
I've found another way to use the keyword LIMIT in subqueries that actually works. Just place your subquery in the FROM of another select and use that one as your subquery, as in the following example:
SELECT COUNT(*) FROM TABLE_1 WHERE ROW (PK_PART_1, PK_PART_2) IN
(SELECT * FROM (SELECT PK_PART_1, PK_PART_2 FROM TABLE_2 LIMIT 10) Alias)
Add your own comment.