相関サブクエリー は、外部クエリー内にも現れるテーブルの参照を含むサブクエリーです。例 :
SELECT * FROM t1 WHERE column1 = ANY
(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
サブクエリーの FROM
節がテーブル t1
に言及しなくても、サブクエリーは
t1
のカラムへの参照を含むということを覚えておいてください。ですので、MySQL
はサブクエリーの外側を見て、外部クエリー内の
t1 を見付けます。
テーブル t1 が
column1 = 5 と
column2 = 6
の場所で行を含み、一方、テーブル
t2 は
column1 = 5 と
column2 = 7
の場所で行を含むと仮定してください。単純な式
... WHERE column1 = ANY (SELECT
column1 FROM t2) は
TRUE
となるでしょうが、例の中では、サブクエリー内の
WHERE 節は
FALSE
ですので、((5,6) が
(5,7)
と同等ではないため)
このサブクエリー全体としては
FALSE です。
スコープルール: MySQL は内側から外側まで評価します。例 :
SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));
このステートメントの中では、SELECT
column1 FROM t2 AS x ... が
t2
をリネームするので、x.column2
はテーブル t2
内のカラムでなければいけません。SELECT
column1 FROM t1 ... は
とても遠くにある
外部クエリーなので、これはテーブル
t1
内のカラムではありません。
HAVING か
ORDER BY
節内のサブクエリーに対しては、MySQL
は外部選択リストからもカラム名を探します。
特定の場合には、相関サブクエリーは最適化されます。例 :
valIN (SELECTkey_valFROMtbl_nameWHEREcorrelated_condition)
そうでなければ、それらは役に立たず、スピードも遅くなりがちです。クエリーを結合として書き換えることで、性能を向上させることができるかもしれません。
相関サブクエリー内の総計関数には、この関数に外部参照以外は何も含まれていない場合、かつこの関数が別の関数または式に含まれていない場合、外部参照が含まれている可能性があります。
