はじめに
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文です。これは、社員の中で最も高齢の社員を抽出することを意図しています。
このコードで最初に実行されるパートは、サブクエリの内側である次のクエリです。SQLは、常に最も内側のサブクエリから実行されます。
すると、このクエリの結果は「50」という単一の値(スカラ値)となります。したがって、次のステップは、サブクエリ全体をこのスカラ値で置き換えた次のようなクエリを実行することとなります。
最終的な結果は、図2のようになります。ここまで、特に疑問点はないでしょう。