VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
mysql -u root -p sakila でクライアントを開いてください。
サブクエリの仕組み
COLUMN_LIST を欲しい列に、TABLE_NAME をテーブルに、COLUMN_NAME を
テストする列に、AGGREGATE_FUNCTION を比較対象の値を生成する関数に
置き換えます。
サーバーはサブクエリを実行し、その結果を受け取って、外側のクエリで使います。
ちょうど 1 行 1 列を返す、かっこで囲まれたサブクエリはスカラーサブクエリ
であり、値のように振る舞います。それが以下の形であり、最もよく問題を起こす
形です。
例
- 書き下せない値を使う
最も長い映画の長さは分からないので、その場で求めます。
MAX(length) 単独では 185 だけが得られ、それ以外は何も得られません。
サブクエリはそれを WHERE に戻すので、映画も得られます。
- 選択リスト内のサブクエリ
同じ値を選択リストに置くこともでき、そこではすべての行で繰り返されます。
- リストを返すサブクエリ
IN に渡すサブクエリは多くの行を返すことが許されます。
IN は値ではなくリストを期待するためです。
IN は各俳優をそのリスト
全体に対してテストします。
ERROR 1242 はサブクエリが多すぎる行を返したことを意味する
= は 1 つのものを 1 つのものと比較します。1,000 行を返すサブクエリを与えると、
サーバーは先に進めません。
- リストが欲しかったのなら、
=の代わりにINを使います。 - 集合から 1 つの値が欲しかったのなら、
MAX()などの集計関数を追加します。 - どの 1 行でもよく、
ORDER BYでどれかを指定できるなら、LIMIT 1を追加します。
ERROR 1242 は少なくとも、はっきりエラーを出して失敗します。この間違いの、
エラーを出さない版は、行を 1 つも返さないサブクエリです。それは NULL を返し、比較は
NULL になり、外側のクエリは静かに何も返しません。
まとめ
- 1 つのクエリの答えを別のクエリに渡すにはサブクエリを使います。
- 1 行 1 列のスカラーサブクエリは値のように振る舞うと考えてください。
ERROR 1242は、多くの行を返したサブクエリに対する=として読みます。- サブクエリがリストを返すときは、
=ではなくINを使います。 - 外側のクエリがエラーなしに何も返さないときは、空のサブクエリを疑います。
関連項目
- 相関サブクエリ — 外側の行を読むサブクエリ
- IN — サブクエリからのリストを受け入れる演算子
- 派生テーブル — テーブルとして使うサブクエリ
- MySQL におけるサブクエリと JOIN の比較 — どの形を選ぶか、それぞれのコスト