相関サブクエリー は、外部クエリー内にも現れるテーブルの参照を含むサブクエリーです。例 :
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
は外部選択リストからもカラム名を探します。
特定の場合には、相関サブクエリーは最適化されます。例 :
val
IN (SELECTkey_val
FROMtbl_name
WHEREcorrelated_condition
)
そうでなければ、それらは役に立たず、スピードも遅くなりがちです。クエリーを結合として書き換えることで、性能を向上させることができるかもしれません。
相関サブクエリー内の総計関数には、この関数に外部参照以外は何も含まれていない場合、かつこの関数が別の関数または式に含まれていない場合、外部参照が含まれている可能性があります。