破壊的なサブクエリ
よくあるSQLクエリの間違いに関するこのシリーズでは、最初の検査では完全に安定しているように見えるが、誤った結果やパフォーマンスの低下につながる可能性のあるSQLクエリの例をいくつか見てきました。先週、述語の配置がクエリの実行にどのように悪影響を与える可能性があるか - 特に外部結合で影響があるかを学びました。今日の記事では、サブクエリと、サブクエリがその基になるテーブルに変更が加えられた時にどのようにSQLステートメントを破壊するかに焦点を当てます。
単一値のサブクエリ対複数値のサブクエリ
単一値と複数値のサブクエリを比較する前ですが、サブクエリとは何かについて簡単に説明する必要があります。サブクエリとは、より大きなクエリ内にネストされた完全なSQLクエリです。サブクエリは、SELECT、FROM、およびWHERE句に配置できます。
サブクエリとは何か、クエリのどこに配置できるかがわかりました。注目すべきは、SELECTクエリと同様に、サブクエリは1行またはそれより多い行を返す場合があるということです。この区別は、クエリステートメントの記述方法に影響を与えるため、非常に重要です。例えば、Navicat Premium 16のSakilaサンプルデータベースに対する次のクエリは、映画「ALONE TRIP」に登場した全ての俳優を取得します。

「ALONE TRIP」という名前のフィルムは1つしかないはずなので、equals(=)演算子を使用してfilm_idsを照合できます。
上記のクエリを次のクエリと比較してください。

この場合、サブクエリは映画に登場した全ての俳優を選択します。当然、このサブクエリは複数の行を返します。その場合、actor_idを照合するためにIN()関数を使用する必要があります。
単一行のサブクエリがどのように機能するか
前述のように、サブクエリはSELECT句に配置されて、メインクエリテーブルに何らかの形で相関している列をフェッチできます。例えば、Navicat Data Modelerに表示されている次の2つの関連するproductsとfactoriesのテーブルについて考えてみます。

productsとfactoriesのテーブルは、共通のskuフィールドを使用してリンクされています。
それでは、各製品のfactory_idを抽出するクエリを作成しましょう。これを行う1つの方法は、相関サブクエリを使用してクエリを記述し、製品のfactory_idを取得することです。

ここでのポイントはテクニックを説明することですので、同じ情報を取得するためのより効率的な方法はあります。いずれにせよ、正しい結果セットが得られ、全て順調です。
会社が売上が増加したので新しい工場を建設することを決定する日が来るまで、そのクエリは完全にうまく機能し続けます。

factoriesテーブルに余分な行があると、クエリでエラーが生成されます。

エラーは、外部クエリがスカラー値を期待していたことを示していますが、サブクエリは結果セットを返しました。JOINを使用して、問題を修正し、各製品を製造している全ての工場を一覧表示できます。

もう1つ...
"column = (SELECT value FROM Table)"のように、列または式がサブクエリに対してテストされる全ての句で同じエラーが発生する可能性があることに注意してください。その場合の解決策は、等式(=)演算子の代わりにIN()関数を使用することです。