副問い合わせ

データベース

基本的な副問い合わせ

1つの値を求める副問い合わせの例

【item_list】テーブルを用いて、『単価が平均より高い商品』を得るSQLを考えてみましょう。
ここまでの作業で、【item_list】テーブルには以下のレコードが登録されているはずです。

平均単価を求めるには、以下のSQLを実行します。

SQL
 SELECT AVG(price) FROM item_list

結果は、

となります。
この値3916.6667を用いて、

SQL
 SELECT * FROM item_list WHERE price>=3916.6667;

とすれば、

という結果が得られます。
このように、いままで学んできた範囲では、手作業で1つめのSQLで求められた結果を2つめのSQLの条件式に記述しなければなりませんでした。
それではさすがに不便です。

というわけで、実はSELECT文の中にさらにSELECT文を記述して、1つにまとめることができます。
この例の場合は次のようになります。

SQL
 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』ならば

SQL
 SELECT student_id FROM score WHERE subject_id='D01' AND score>=80;

で取得できるはずです。
これを単独で実行すると

となります。
これを副問い合わせとして、

SQL
SELECT student_name FROM student_list
   WHERE student_id=(SELECT student_id FROM score WHERE subject_id='D01' AND score>=80);

とすればよさそうに思えます。
実際にこれを実行すると、

を得ることが出来ます。
では、SQLの構造はそのままに、条件を『80点以上』から『70点以上』にするとどうなるでしょうか?

SQL
SELECT student_name FROM student_list
   WHERE student_id=( SELECT student_id FROM score WHERE subject_id='D01' AND score>=70);

すると今度は『サブクエリが2行以上の結果を返します。』というエラーが発生してしまいます。

ためしに、副問い合わせの部分

SQL
 SELECT student_id FROM score WHERE subject_id='D01' AND score>=70;

を単独で実行すると、

と、2件のレコードが抽出されています。
主問い合わせのWHERE句では student_id=○ と条件が記述されていますが、等号『=』では複数の値との比較が出来ないためエラーとなってしまっているのです。

それではどうしたらよいでしょうか?

WHERE句で用いる様々な条件式を思い出してみましょう。

『あるカラムの値が、複数の値のいずれかである』

という条件を記述するのには、IN句を用いました。
これを用いて、

SQL
SELECT student_name FROM student_list
   WHERE student_id IN (SELECT student_id FROM score WHERE subject_id='D01' AND score>=70);

SQLを記述すると、今度は

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

コメント

タイトルとURLをコピーしました