サブクエリを使って絞り込もう

1つ目のSQL文を実行して出てきた値を用いて2つ目のSQL文の条件指定としたい場合、普通に書けばSQL文を2つ逐次実行することになるかと思います。

このとき、サブクエリを使うことで一つのSQL文だけで表現できるようになります。

人の手を入れず、自動で目的とする値を一発のSQLで出したい場合に有用です。

書き方

  • 列Aの値が、サブクエリとして指定した2つ目のSQLの結果と等しいデータを抽出したい場合
SELECT * FROM <テーブル名> WHERE 列A = (SELECT 列名 FROM <テーブル名> WHERE <ただ一つのデータだけに絞り込める条件>);
  • 列Aの値が、サブクエリとして指定した2つ目のSQLの結果のいずれかを含むデータを抽出したい場合
SELECT * FROM <テーブル名> WHERE 列A IN (SELECT 列名 FROM <テーブル名> WHERE <絞り込み条件>);

書き方の説明

これまでに学習してきたSQLの文法を組み合わせているだけにすぎません。

サブクエリの特徴として、今まで固定的な値を指定した箇所(列A = X や、 列A IN (X, Y, Z)としてきた箇所の右辺)について、

固定的な値ではなくSELECT文を入れただけに過ぎません。

そのSELECT文がサブクエリと言われます。

サブクエリの実行結果について、ただ一つだけのレコードが出てくるのであれば、メインのクエリの絞り込み条件は = が使えます。

一方で、サブクエリの実行結果について、複数のレコードが出てくるのであれば、メインのクエリの絞り込み条件は IN を使ったりします。

また、サブクエリでは抽出する列名はただ一つの列名だけを指定します。サブクエリの実行結果に複数の列が出てきたら、メインクエリで比較ができなくなってしまうからです。

ユーザー情報が入っている users テーブルについて、departmentsテーブルで管理されている部署名が"経理"の部署名を持つdepartment_idのデータだけに絞り込みたい場合

SELECT * FROM users WHERE department_id = (SELECT id FROM departments WHERE name = "経理");

練習

試しに、products テーブルと、owners テーブルで練習してみましょう!

productsテーブルには商品情報が、ownersテーブルにはproductsテーブルに入っている商品を卸している企業のデータが入っているとします。

このとき、ownersテーブルでは資本金の額が管理されているとした場合、資本金の額が1000円以上の企業が卸している商品一覧を抽出したい場合には、次のようなSQLになります。

問題

売上情報を管理する sales というテーブルがあります。また、この売上情報を管理するテーブルの他に、ユーザー情報を管理するusersというテーブルがあります。salesのデータには、user_idが管理されているのでusersと紐付けられていますが、ユーザー情報のうち、生年月日が1970年10月25日より後のユーザーによる売上データを抽出してみましょう。

答え合わせ

正解を見る
正解:SELECT * FROM sales WHERE user_id IN (SELECT id FROM users WHERE birthday > "1970-10-25");
解説:まず、生年月日が1970年10月25日より後のユーザーに絞り込むSQLを考えます。その後、売上情報をそのユーザー達に絞り込む条件を考えれば、答えの通りとなります。