SQLアタマアカデミー

第9回SQLでループ! 相関サブクエリの使い方~切れ過ぎるナイフにご用心~ (1)サブクエリ

はじめに

SQLを使い始めたとき、多くのプログラマが例外なく難儀するのが、SQLで制御構造をうまく書けないことです。ここで言う制御構造とは、平たく言えば条件分岐とループです。といっても別に、SQLに制御構造を書くための機能が備わっていないとか、貧弱というわけではありません。SQLでも、通常の手続き型言語と同等の制御構造を記述することができます。ただ、そのやり方が一風変わっているので、うまく「SQLアタマ」に切り替えられないと戸惑ってしまうのです。

そういう「普通の」プログラマやSEの違和感を軽減するための橋渡しをするのが、本連載の目的の1つでもあるので、これまでにもSQLで制御構造を記述する方法については折に触れて取り上げてきました。しかし、条件分岐のためのCASE式に対して、ループのための道具はそれほど十分に解説してこなかったかもしれません。そこで今回は、SQLでループを記述する方法を中心に解説したいと思います。

そのための中心的な道具がサブクエリ、特に2つのテーブルを関係づけて使う相関サブクエリco-related subqueryです。これは、一般的にSQLの中で一番ややこしいと思われている技術で、敬遠されがちです。でも、筆者はそうは思っていません。むしろ、論理的にかっちりしているので、動作イメージがつかめれば、第8回で取り上げたNULLと真理値の混乱ぶりに比べれば、ずっとすっきり理解できるものです。

結論から書いてしまうと、相関サブクエリの動作イメージは、集合のカット(分割)です。このカットという操作については、連載SQLアタマ養成講座でも、GROUP BYやPARTITION BYが持つ機能としてお話しました。手続き型言語がレコード単位で考えるのに対し、SQLがレコードの「集合」レベルで考える言語なのだということを、本稿で再度認識してもらえればと思います。

読者対象
  • SQLでループを記述したい人
  • 過去、SQLを勉強してサブクエリから相関サブクエリへ進んだ時点で敗れ去った人
稼働環境
  • すべてのリレーショナルデータベース

それではさっそく、具体的なサンプルをもとに相関サブクエリのメカニズムを解き明かしていきたいと思います。まずは単純なサブクエリから相関サブクエリに変わったとき、何が変わるのかを見てみましょう。使うテーブルは、図1の社員テーブルです。

図1 解説に使用する社員テーブル

Employees

emp_id
(社員ID)
name
(社員名)
dept
(部署)
sex
(性別)
age
(年齢)
001橋本営業37
002山下営業24
003石川営業40
004中島総務35
005前田総務26
006藤田総務50
007小川開発29
008長谷川開発29

サブクエリ

出発点とするのは、リスト1のようなサブクエリを含むSELECT文です。これは、社員の中で最も高齢の社員を抽出することを意図しています。

リスト1  サブクエリ(集合のカットなし)
SELECT *
  FROM Employees E1
 WHERE age = (SELECT MAX(age)
                FROM Employees E2);

このコードで最初に実行されるパートは、サブクエリの内側である次のクエリです。SQLは、常に最も内側のサブクエリから実行されます。

最初に実行されるクエリ
SELECT MAX(age)
  FROM Employees E2;

すると、このクエリの結果は「50」という単一の値(スカラ値)となります。したがって、次のステップは、サブクエリ全体をこのスカラ値で置き換えた次のようなクエリを実行することとなります。

SELECT *
  FROM Employees E1
 WHERE age = 50;

最終的な結果は、図2のようになります。ここまで、特に疑問点はないでしょう。

図2 リスト1の実行結果
emp_id  name   dept   sex    age
------- ------ ------ ------ -----
006     藤田   総務   女     50

おすすめ記事

記事・ニュース一覧