- 6.1. 基本的な結合
- 6.2. 自己結合
- 6.3. 特殊な結合演算子
- 1. CROSS JOIN
- 2. 自然結合
- 3. 指定結合
- 4. UNION JOIN
6.1. 基本的な結合
最も基本的な結合は自然結合と呼ばれるもので、データベース構造に既に存在しているリレーションシップを表現するところからきています。ちなみに受注表、顧客表及び商品表のリレーションは次の図のようになっています。
受注表からは受注番号に対応する顧客コードと商品コードを知ることができます。そして、これらの列は外部キーとなっているため、リンクされる顧客表と商品表からコードに対する名称を知ることが可能です。よって、受注番号、顧客名、商品名、受注個数及び納品日の列を持つ表を、表の結合により作成することができるのです。ちなみに、受注表における受注番号、顧客表における顧客コード及び商品表における商品コードは各テーブルの主キーです。
図のようにテーブルを結合するには、これまでのテーブルのデータを参照する時と同様に SELECT 文を用います。SELECT 文に続けて、表示する列名を指定し、FROM のあとに指定した列の属するテーブル名を指定します。また、どのテーブルのどの列で結合するのかも条件として指定します。図の例の場合、sample.17-1 ように SQL を記述します。
-- sample.17-1 --/* テーブルの結合 */ SELECT 受注表.受注番号,顧客表.顧客名, 商品表.商品名,受注表.受注個数,受注表.納品日 FROM 受注表,顧客表,商品表 WHERE 受注表.顧客コード = 顧客表.顧客コード AND 受注表.商品コード = 商品表.商品コード ;
/* 実行結果 */ 受注番号 顧客名 商品名 受注個数 納品日 ─────── ───────────── ────── ──────── ────── 10001 KUROKIYA JUICE 300 20010401 10002 ONSIDE BEER 200 20010401 10003 KUSHINANA BEER 150 20010401 10004 KUSHINANA JUICE 80 20010402 10005 ONSIDE WINE 110 20010402 10006 KUROKIYA TEA 250 20010402 10007 FIRST HOUSE JUICE 45 20010402 10008 KUSHINANA BEER 135 20010403 10009 FIRST HOUSE TEA 65 20010403 10010 KUROKIYA BEER 290 20010403 10011 FIRST HOUSE TEA 60 20010404 10012 KUSHINANA BEER 175 20010404
sample.17-1 では、列の指定の仕方がこれまでの説明と異なっています。テーブルの結合では、複数のテーブルから列を参照するため、列名を指定する際には列が属するテーブル名も明記しなければなりません。
列名の指定 → 属するテーブル名.列名
これまで列の属するテーブルを明記してこなかったのは、参照する列が FROM 句で指定したテーブルに属しているのが明らかだったからです。ですから、FROM 句で複数のテーブルを参照する場合には、どのテーブルのどの列なのかということを明記しなければならないのです。しかし、全ての列名が異なる場合、たとえば受注表の顧客コードが顧客番号、受注表の商品コードが商品番号という名前であるような場合は、テーブル名を明記する必要はありません。しかし、一般的にわかりやすさという観点から、きちんとテーブル名を明記することがよいとされているようです。
SQL の基本的な結合作業は、結合されたテーブルを取り出して、考えられる限りの行の組み合わせを調べ、結合された 2つ以上のテーブルから 1 行ずつ取り出すというものです。この操作は、デカルト積と呼ばれています。
先ほどのサンプルでは、DBMS はまず受注表の顧客コードと顧客コードを照らし合わせて、その組み合わせが TRUE を形成する時、すなわちその値が一致する時、その組み合わせから出力する値を選択します。同時に受注表の商品コードと商品表の商品コードを照らし合わせて、その値が一致する時、出力する値を選択します。そして、SELECT に続く列名についてのデータを表示します。
このように、外部キーを親キーに結び付けている結合を自然結合と言います。しかし、SQL では設計されたリレーションシップによるデータの抽出だけでなく、データの内容に基づくリレーションシップによるデータの抽出も行えます。たとえば、納品日が '20010401' の日に納品する商品名を抽出するには次のように SQL を書きます。
-- sample.17-2 --/* テーブルの結合 */ SELECT 受注表.納品日,商品表.商品名 FROM 受注表,商品表 WHERE 受注表.納品日 = '20010401' AND 受注表.商品コード = 商品表.商品コード ;
/* 実行結果 */ 納品日 商品名 ──────── ───── 20010401 JUICE 20010401 BEER 20010401 BEER
'BEER' が二つ表示されますが、SELECT の後に「DISTINCT」を置けば、重複するものを表示させないようにできます。
実習課題 1
ある自動車メーカーの販売管理データベースに用意されているテーブル customer と office から、各営業所が抱えている顧客が何名いるのかを確認する SQL 文を記述しなさい。営業所名と顧客の人数を表示すること。
実習課題 2
販売管理データベースから、支払った金額の大きいもの順に、顧客名と支払った合計金額を表示する SQL 文を記述しなさい。一回あたりの支払い金額は、次の式で求めるものとする。複数台自動車を購入した顧客はそれらすべてを合計したものを支払い金額とする。
- (製品の価格) x (100 - (製品の値引率)) / 100 + (オプションの価格)
- = product.price x (100 - accept_order.dc_rate) / 100 + accept_order.option_price
顧客名とその支払い金額を表示すること。
実習課題 3
販売管理データベースから、2001年 3月中に各従業員の自動車販売件数を、販売件数の少ないものから順に表示する SQL 文を記述しなさい。従業員名と販売件数を表示すること。