こんにちは!21卒エンジニアの松尾です。
今回SQLで意外と使う『副問い合わせ(サブクエリ)』について紹介しようと思います。
副問い合わせとは
副問い合わせ(サブクエリ)とは、SQL文の中に入っているSQL文(クエリ)のことです。
例えば
SELECT 列名, (SELECT~…)
となっている文です。
ちなみのこの副問い合わせ、必ずしも SELECT 列名, の次に書かれるとは限りません。FROM句、WHERE句の次に書かれることもあります。
・SELECT句
SELECT 列名, (SELECT~…) AS 別名 FROM 表名 WHERE 条件;
・FROM句
SELECT DB名.列名 FROM (SELECT~…) 別名 WHERE 条件;
・WHERE句
SELECT 列名 FROM WHERE 列名 = (SELECT~…)
※(SELECT~…)の部分が副問い合わせです。
↓↓↓実際に表を使って説明していきます↓↓↓
商品リスト
商品ID | 商品名 | 商品価格 |
0001 | にんじん | 72 |
0002 | じゃがいも | 72 |
0003 | きゅうり | 71 |
0004 | ナス | 63 |
0005 | トマト | 136 |
0006 | しいたけ | 248 |
0007 | エリンギ | 94 |
0008 | 白菜1/4カット | 94 |
明細No | 番号 | 商品ID | 数量 |
1 | 1 | 0003 | 3 |
1 | 2 | 0006 | 5 |
2 | 1 | 0001 | 2 |
2 | 2 | 0002 | 1 |
2 | 3 | 0003 | 5 |
3 | 1 | 0003 | 3 |
3 | 2 | 0004 | 4 |
3 | 3 | 0006 | 1 |
4 | 1 | 0001 | 3 |
こんな感じのテーブルがあったとして、実際に売り上げになっている商品だけを抽出したいときに副問い合わせが使われます。
『商品リストのうち、売上表に記載がある商品を抽出する』
がわかりやすいですね。
実際にSQLを書く
SELECT 商品ID, 商品名 --主問い合わせ
FROM 商品リスト
WHERE EXISTS --このEXISTSは後ほど説明します
( SELECT * --ここのSELECTが副問い合わせ
FROM 売上表
WHERE 売上表.商品ID = 商品リスト.商品ID
)
これが実行されるとどのような結果が返ってくるんでしょう?
結果
商品ID | 商品名 |
0001 | にんじん |
0002 | じゃがいも |
0003 | きゅうり |
0004 | ナス |
0006 | しいたけ |
結果は左のようになります。
ここで使われているEXIST句は、サブクエリを扱うためのものです。
SELECT文で取得した結果を他のSELECT・UPDATEで使用する。
つまりSELECTの結果を更にSELECTすることです。
2つ以上の表から特定の条件を抽出するやり方としてJOINがありますが、
JOINで書いてみるとどのような文になるんでしょう?
JOINで書いてみる
SELECT DISTINCT 商品リスト.商品ID, 商品リスト.商品名
FROM 商品リスト
INNER JOIN 売上表
ON 商品リスト.商品ID = 売上表.商品ID
こうなると思います。
一見JOINの方が楽そうに見えますが、重複排除したい場合DISTINCTを記載しなくてはならない上に、OUTER JOIN・INNER JOIN・CROSS JOINそれぞれどういった結果が返ってくるのかを理解していることが前提になってきます。
(理解している方はそう苦労しないかもしれませんが…)
【補足】EXISTSとは
上の例文で出てきたEXISTSはサブクエリを扱う仕組みで、『相関副問合せ』とも言います。副問い合わせによってレコードが返ってこれば真、来なければ偽を返してきます。
なので、上のDBで説明すると
・商品リストの1行目はにんじん、存在しているので真として値を返します
(結果ににんじんが追加される)
・商品リストの2行目はじゃがいも、存在しているので真として値を返します
(結果にじゃがいもが追加される)
………………………………………………………………………………………………
これを続けていくと商品ID 0005のトマトで偽を返すことに気が付きます。
ここで偽が返されるとどうなるのかというと、主問い合わせで抽出されず次のレコードを判定しに行きます。
次のレコードはしいたけが入っているのでここでまた真を返して、結果に追加されます。
おわりに
学校やどこかでたびたび聞いた『副問い合わせ』ですが、一文一文読んでいくととても便利ですね。
今回はSELECT句での副問い合わせで抽出しましたが、FROM句、WHERE句で抽出してみるのも面白いかもしれません。
簡単な説明でしたが何かで役に立てれば幸いです。
コメント