副問い合わせとは
副問い合わせとは、
SQL文の内部に別のSELECT文を記述すること。
- 1つのSQL文で2つ以上の処理ができ、DBMSに対して柔軟な指示ができる仕組み。
副問い合わせは、()で括って記述する。
WHERE・SELECT・FROM・HAVING句、INSERT/UPDATE/DELETE文などさまざまな場所で使える。
内側のSELECT文(副問い合わせ)」が先に実行され、
その結果を使って「外側のSQL文(主問い合わせ)」が実行される。副問い合わせの中でさらに副問い合わせを使える(ネスト)が、SQLが複雑になりやすい。
副問い合わせの種類
内側のSELECT文の結果の構造や依存関係によって、3つに分けられる。
1.単一行副問い合わせ(スカラーサブクエリ)
- 「1つの値(1行1列)」だけを返す。
- 比較演算子で直接比較ができる。
SELECT * FROM orders WHERE price = (SELECT MAX(price) FROM orders );
☀︎ordersテーブルの最も高い価格のすべての列を取得できる。
2.複数行副問い合わせ
- 「複数の値(複数行1列)」を返す。
- 比較演算子だけではエラーとなるため、
IN/NOT IN、ANY/ALL演算子やEXISTS / NOT EXISTSを使う。
IN / NOT IN(条件に当てはまるものを抽出)
SELECT * FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE price >= 5000 );
☀︎5,000円以上の注文履歴がある顧客の情報一覧を取得できる。
- NOT INでは「5,000円以上の注文履歴がない顧客」と否定形となる。
3.相関副問い合わせ
- 外側のテーブルの値を1行ずつ副問い合わせに渡して実行し判定する。
そのため、各行ごとに異なる結果となり条件に当てはまった行のみ返す
EXISTS(存在のチェック)
- 外側のテーブルの各行ごとに副問い合わせを実行し、TRUEかFALSEの判断を繰り返す。
- そのデータが副問い合わせの中に存在すると「真」、存在しないと「偽」となる。
NOT EXESTSは真と偽が反対になる。
SELECT * FROM customers WHERE EXISTS ( SELECT customer_id FROM orders WHERE orders.customer_id = customers.id );
☀︎ordersテーブルに注文履歴がある顧客の情報一覧を取得できる
副問い合わせとJOIN句の使い分け
複数行副問い合わせの「5,000円以上の注文履歴がある顧客の情報一覧」を、
JOINを使って書くこともできる。
SELECT DISTINCT customers.* FROM customers JOIN orders ON orders.customer_id = customers.id WHERE orders.price >= 5000;
副問い合わせは
- 条件付きの絞り込みや複雑な条件・集計結果に使うと便利。
- FROM句で使うと、一時的なテーブルのように扱える。
- 大量データのときは処理が遅くなりやすい。
JOIN句は
- 複数テーブルのカラムを同時に取得するときや、関連データをまとめて処理したいときに使う。
- 複数のテーブルを組み合わせた集計や分析に便利
- インデックスが貼られている場合、大量データでも高速に処理ができる。