読者です 読者をやめる 読者になる 読者になる

Jの衝動書き日記

さらりーまんSEの日記でございます。

 第1回 SELECTをあなどるなかれ

人に教える事が一番効率がよい学習方法だという話を読んだ覚えがあるので、それにしたがって書いてみた。学習元は大抵『データベースパフォーマンスアップの教科書』である。
今日のポイントは、SELECTは表取得操作にあらず。集合の操作なりである。

1.SELECTは表取得操作にあらず

データベースを触った事がある人なら、一度は目にしたことがあるSELECT。まずはその扱いの認識を改めることから始めたい。

1.1 SELECTの定義

SELECT文の解説を見ると、大抵以下のように解説されていると思う。

SELECT 列名 [,列名...] → もしくは*
FROM テーブル名 [,テーブル名...]
[WHERE 条件式]

例えば、得意先テーブルから、担当部署が第一営業部であるレコードを取得し、列名:得意先名と住所を表示する場合、以下のように書く。

SELECT 得意先名,住所 FROM 得意先 
WHERE 担当部署コード = 第一営業部コード

ようするに、テーブルに存在するレコードを条件と表示する列名を指定することでデータを取得するわけである。データベース操作の基本中の基本なので、難しいことはないだろう。

だが、上記のテーブル名は、データベース上のものではなくてもよく、列名・値に関してもテーブル上に存在しないものでもよい、というルールを与えられた途端よくわからなくなる。以下に示す例は、いずれもきちんと応答が返ってくる。

例1
 SELECT
  商品コード, 商品名,単価 * ロット数 as 販売価格,'特価品' as 商品種別
 FROM 商品_特価 ..略

例2
 SELECT 商品名.ソート_売上金額
 FROM
  (SELECT * FROM 商品売上
   ORDER BY 売上金額) as ソート_売上金額
 WHERE ROWNUM <= 5

例1に関しては表:商品_特価の列を計算した結果である販売価格や、表にはない仮想列:商品種別を取得している。例2に関しては、売上金額でソートした商品売上テーブルの仮想テーブルであるソート_売上金額から5件だけデータを取得している。
SELECTは、単なる表取得操作ではないのだ。

1.2 SELECTとは、集合の操作

では何か?というと、『SELECTとは集合を取得するための操作である』と考えるとスッキリする。以下のように定義してみる。

SELECT 取得したい集合(Select-List)(列名1、列名2、・・・)
FROM 取得する対象となる集合1,集合2,..(From-List)
[WHERE 条件式]

つまり、データベースから取得したい値の集合を、Select-Listにて示し、その集合を作成するためにデータを取得する対象をFrom-Listで示すわけだ。Select-Listに関しては、求める値がFrom-Listの集合にない場合、値の取得方法を指定することも出来る。
1.1の例1では、データベースから(商品コード,商品名,販売価格,商品種別)の形の集合を取得したかった。しかし、取得先の集合として指定した 商品_特価には、販売価格は、単価とロット数という形で分かれ、商品種別はそもそも集合の中には無かった。そのため、Select-Listの中で、販売価格と商品種別の値の取得方法を示すことで、求めたい集合を作成したわけである。
例2では、データベースから売上金額のBest5の商品名を取得したかった。しかし、取得元となる集合:商品売上は売上金額ではソートされていないため、ソートした集合:ソート_売上金額を作成し、その中から上位5件を取得したわけである。仮想列、仮想表、と考えるよりも集合と考えるとスッキリする。
ちなみに、条件式においても集合を条件として扱える。

SELECT 従業員番号 FROM 従業員
WHERE 所属 IN (SELECT 部門番号 FROM 部門 WHERE ...)

いわゆる副問い合わせという奴だ。副問い合わせで条件となる所属の集合を作成してから検索しているわけである。これからもSELECTは表操作の結果を返すのでなく、集合を返すと言った方がスッキリする。

ちなみに、From-Listに関しては、指定なしでも出来る(Oracleの場合はDUALを指定する必要はあるが)。つまり、Select-Listに集合の値をすべて指定してしまうことも出来るのである。これを利用して、テーブル定義が固まる前に画面部分だけを作成してしまえという提案をする方もいる(ベンチャー社長で技術者で: テーブル設計は実装の後に!)。

参考文献・URL