基本的な副問い合わせ
1つの値を求める副問い合わせの例
【item_list】テーブルを用いて、『単価が平均より高い商品』を得るSQLを考えてみましょう。
ここまでの作業で、【item_list】テーブルには以下のレコードが登録されているはずです。

平均単価を求めるには、以下のSQLを実行します。
SELECT AVG(price) FROM item_list結果は、

となります。
この値3916.6667を用いて、
SELECT * FROM item_list WHERE price>=3916.6667;とすれば、

という結果が得られます。
このように、いままで学んできた範囲では、手作業で1つめのSQLで求められた結果を2つめのSQLの条件式に記述しなければなりませんでした。
それではさすがに不便です。
というわけで、実はSELECT文の中にさらにSELECT文を記述して、1つにまとめることができます。
この例の場合は次のようになります。
SELECT * FROM item_list WHERE price>=(SELECT AVG(price) FROM item_list); 2つめのSELECT文の条件式で単価の平均である『3916.6667』が書かれていた場所に、その値を求めるために用いた1つめのSQL文をそのまま記述しています。
これでも先の物とまったく同じ結果を得ることが出来ます。
このようにSELECTの中にSELECTが入れ子になった文では、
最終結果(この例では『平均よりも単価が高い商品』)を得るための問い合わせ(SQL文)を『主問い合わせ』
その中に挿入された、条件値など(この例では『平均単価』を求めるための問い合わせ)を『副問い合わせ』
といいます。
副問い合わせの結果が複数になる場合
【student_list】テーブルと【score】テーブルを組み合わせ、『subject_id=’D01’の試験で80点以上をとった学生の名前』を取得するSQLを、副問い合わせを用いて記述してみましょう。
※結合して通常のWHERE句に条件を記述すればできますが、今回は練習のために敢えて副問い合わせを使います
『subject_id=’D01’の試験で80点以上をとった学生のstudent_id』ならば
SELECT student_id FROM score WHERE subject_id='D01' AND score>=80;で取得できるはずです。
これを単独で実行すると

となります。
これを副問い合わせとして、
SELECT student_name FROM student_list
WHERE student_id=(SELECT student_id FROM score WHERE subject_id='D01' AND score>=80);とすればよさそうに思えます。
実際にこれを実行すると、

を得ることが出来ます。
では、SQLの構造はそのままに、条件を『80点以上』から『70点以上』にするとどうなるでしょうか?
SELECT student_name FROM student_list
WHERE student_id=( SELECT student_id FROM score WHERE subject_id='D01' AND score>=70);すると今度は『サブクエリが2行以上の結果を返します。』というエラーが発生してしまいます。
ためしに、副問い合わせの部分
SELECT student_id FROM score WHERE subject_id='D01' AND score>=70;を単独で実行すると、

と、2件のレコードが抽出されています。
主問い合わせのWHERE句では student_id=○ と条件が記述されていますが、等号『=』では複数の値との比較が出来ないためエラーとなってしまっているのです。
それではどうしたらよいでしょうか?
WHERE句で用いる様々な条件式を思い出してみましょう。
『あるカラムの値が、複数の値のいずれかである』
という条件を記述するのには、IN句を用いました。
これを用いて、
SELECT student_name FROM student_list
WHERE student_id IN (SELECT student_id FROM score WHERE subject_id='D01' AND score>=70);SQLを記述すると、今度は

と結果を得ることが出来ます。
このように、副問い合わせで複数のレコードが得られる可能性がある場合には、条件式に『=』ではなく『IN』を用います。


コメント