SQL のネストされたクエリ

SQL 言語を使用すると、あるクエリを別のクエリ内にネストできます。これにより、コードの読みやすさは大幅に低下しますが、大規模で複雑な処理を実行する 1 つの非常に大きなクエリを作成することが可能になります。

サブクエリで返される値の数に応じて、適用できる範囲が変わります。合計 3 つのオプションがあります。

  • サブクエリは1 つの値(1 つの列と 1 つの行) を返します。
  • サブクエリは値のリスト(1 つの列を持つテーブル) を返します。
  • サブクエリはテーブル(多数の列、任意の数の行) を返します。

それぞれのケースについて 1 つの例を見てみましょう。

スカラー結果を含むサブクエリ

従業員テーブルから、会社の平均より給与が高い全従業員のリストを見つけてみましょう。どうすればできるでしょうか?

給与が事前にわかっていれば、給与と平均を比較して従業員を簡単にフィルタリングできます。同時に、会社の従業員の平均給与を計算できるクエリをすでに作成しました。覚えておきましょう:

SELECT AVG(salary) FROM employee 

次に、MySQL は値76833.3333を返しました。

平均以上の給与を持つすべての従業員のリストを見つけるにはどうすればよいでしょうか? これも非常に簡単です。

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

このクエリの結果は次のようになります。

ID 名前 職業 給料
1 イワノフ・イワン プログラマー 100000
2 ペトロフ・ペトル プログラマー 80000
4 ラビノビッチ・モイシャ 監督 200000

ここで、値 76833 の代わりに最初のリクエストを置き換えて、両方のリクエストを結合します。

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

このクエリの結果は同じになります。

ID 名前 職業 給料
1 イワノフ・イワン プログラマー 100000
2 ペトロフ・ペトル プログラマー 80000
4 ラビノビッチ・モイシャ 監督 200000

値のリストを含むサブクエリ

かつて、あるテーブルから対応するレコードが存在しないレコードをすべて検索するというタスクがあったことを覚えていますか?

こんな写真もありました:

私の記憶が間違っていなければ、タスクは次のとおりです。タスク テーブルにタスクがないすべての従業員のリストを従業員テーブルから表示します。

2 つのステップで解決策を見つけてみましょう。

まず、タスク テーブルにタスクを持つすべての従業員の ID を返すクエリを作成しましょう。次の 2 つのことを覚えておいてください。

  • 重複を削除 - DISTINCT キーワードを使用します。
  • 結果から NULL 値を削除します。
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

そして、このようなリクエストの美しい結果が得られました。

従業員ID
1
2
5
4
6

便宜上、1、2、5、4、6 というシーケンスとして一時的に書き留めてみましょう。次に、従業員テーブルに 2 番目のクエリを作成しましょう。これは、最初のリストに含まれていない ID を持つ従業員のリストを返します。

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

そして、このクエリの結果は次のようになります。

ID 名前 職業 給料 参加日
3 イワノフ・セルゲイ テスター 40000 30 2014-01-01

前の例と同様に、ID リストの代わりに最初のリクエストの本文を置き換えるだけで、両方のリクエストを結合できます。

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )