メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
サブクエリは、別のクエリの中にあるクエリです。まだ知らない答えを使えるように します。最も長い映画、平均のレーティング、何かに一致する id の集合などです。 サブクエリがなければ、2 つのクエリを実行し、最初の結果を手作業で 2 番目に 貼り付けることになります。 始める前に、mysql -u root -p sakila でクライアントを開いてください。

サブクエリの仕組み

COLUMN_LIST を欲しい列に、TABLE_NAME をテーブルに、COLUMN_NAME を テストする列に、AGGREGATE_FUNCTION を比較対象の値を生成する関数に 置き換えます。 サーバーはサブクエリを実行し、その結果を受け取って、外側のクエリで使います。 ちょうど 1 行 1 列を返す、かっこで囲まれたサブクエリはスカラーサブクエリ であり、値のように振る舞います。それが以下の形であり、最もよく問題を起こす 形です。

例

  1. 書き下せない値を使う

最も長い映画の長さは分からないので、その場で求めます。
MAX(length) 単独では 185 だけが得られ、それ以外は何も得られません。 サブクエリはそれを WHERE に戻すので、映画も得られます。

  1. 選択リスト内のサブクエリ

同じ値を選択リストに置くこともでき、そこではすべての行で繰り返されます。
サブクエリは 1 回実行され、その答えが列に沿って複製されます。これが、比較 対象の行の横に値を表示する方法です。

  1. リストを返すサブクエリ

IN に渡すサブクエリは多くの行を返すことが許されます。 IN は値ではなくリストを期待するためです。
内側のクエリは映画 1 に出演する全員の id を返し、IN は各俳優をそのリスト 全体に対してテストします。

ERROR 1242 はサブクエリが多すぎる行を返したことを意味する

= は 1 つのものを 1 つのものと比較します。1,000 行を返すサブクエリを与えると、 サーバーは先に進めません。
意図に応じて、3 つの出口があります。
  • リストが欲しかったのなら、= の代わりに IN を使います。
  • 集合から 1 つの値が欲しかったのなら、MAX() などの集計関数を追加します。
  • どの 1 行でもよく、ORDER BY でどれかを指定できるなら、LIMIT 1 を追加します。
ERROR 1242 は少なくとも、はっきりエラーを出して失敗します。この間違いの、 エラーを出さない版は、行を 1 つも返さないサブクエリです。それは NULL を返し、比較は NULL になり、外側のクエリは静かに何も返しません。

まとめ

  • 1 つのクエリの答えを別のクエリに渡すにはサブクエリを使います。
  • 1 行 1 列のスカラーサブクエリは値のように振る舞うと考えてください。
  • ERROR 1242 は、多くの行を返したサブクエリに対する = として読みます。
  • サブクエリがリストを返すときは、= ではなく IN を使います。
  • 外側のクエリがエラーなしに何も返さないときは、空のサブクエリを疑います。

関連項目