2009/02/02
【誰にでもできる!システム開発】複数テーブルからの選択
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
『誰にでもできる!システム開発』 2009/02/02 号
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ご愛読、ありがとうございます。
このメールマガジンは、システム開発を始めたばかりの方、これから始める
方向けに、筆者が日頃から心がけていることをお話しています。
扱う内容については、テクニックと考え方を半分ずつで構成しています。
思っていた内容と違う、つまらない、読む気力が無くなったという方、
購読解除はこちらからできます。
http://www.mag2.com/m/0000263428.html
著者プロフィール
http://www.shiga-it-office.com/mailmagazine/writer.html
事務所概要
http://www.shiga-it-office.com/profile.html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■第31回 複数テーブルからの選択
────────────────────────────────────
SQLシリーズ、しばらく続きます。
今回は複数テーブルの結合についてです。
そんなの知ってるよという方も多いとは思いますが、引っかかりやすい落と
し穴もありますので、理解しているかチェックしてみてください。
実例を通して紹介しますので、以下のサンプルテーブルをご覧ください。
・取引明細
---------------------------------------------
| 取引番号 | 顧客コード | 商品コード | 数量 |
-----------+------------+------------+-------
| 00000001 | 0001 | A001 | 10 |
-----------+------------+------------+-------
| 00000002 | 0001 | B001 | 5 |
-----------+------------+------------+-------
| 00000003 | 0002 | A002 | 8 |
-----------+------------+------------+-------
| 00000004 | 0003 | A001 | 25 |
-----------+------------+------------+-------
| 00000005 | 0001 | B002 | 15 |
---------------------------------------------
・商品
----------------------------------
| 商品コード | 商品名 | 単価 |
-------------+------------+-------
| A001 | 抹茶ケーキ | 200 |
-------------+------------+-------
| A002 | モンブラン | 250 |
-------------+------------+-------
| B001 | クッキー | 80 |
-------------+------------+-------
| B002 | ビスケット | 70 |
-------------+------------+-------
| C001 | マシュマロ | 100 |
----------------------------------
●複数テーブルからの選択
結合するときは、JOIN句を使います。
例として、取引明細と商品を結合して選択すると、以下のようになります。
SELECT
取引明細.取引番号,
取引明細.商品コード,
商品.商品名,
商品.単価,
取引明細.数量,
商品.単価 * 取引明細.数量 AS 合計
FROM
取引明細 INNER JOIN 商品
ON 取引明細.商品コード = 商品.商品コード
-----------------------------------------------------------
| 取引番号 | 商品コード | 商品名 | 単価 | 数量 | 合計 |
-----------+------------+------------+------+------+-------
| 00000001 | A001 | 抹茶ケーキ | 200 | 10 | 2000 |
-----------+------------+------------+------+------+-------
| 00000002 | B001 | クッキー | 80 | 5 | 400 |
-----------+------------+------------+------+------+-------
| 00000003 | A002 | モンブラン | 250 | 8 | 2000 |
-----------+------------+------------+------+------+-------
| 00000004 | A001 | 抹茶ケーキ | 200 | 25 | 5000 |
-----------+------------+------------+------+------+-------
| 00000005 | B002 | ビスケット | 70 | 15 | 1050 |
-----------------------------------------------------------
結合条件はONの後に記述します。
この例では、取引明細の商品コードと商品の商品コードが一致するレコード
同士が結合しますね。
●外部結合
結合対象のレコードが存在しなくても、外部結合することでNULL値として選
択することが可能です。
例として、先ほどのSQLを商品から見ると、C001の取引明細が存在しないた
め、結合することができませんが、OUTER JOINを使用すると以下のように選
択することができます。
SELECT
取引明細.取引番号,
取引明細.商品コード,
商品.商品名,
商品.単価,
取引明細.数量,
商品.単価 * 取引明細.数量 AS 合計
FROM
商品 LEFT OUTER JOIN 取引明細
ON 取引明細.商品コード = 商品.商品コード
ORDER BY
商品コード, 取引番号
-----------------------------------------------------------
| 取引番号 | 商品コード | 商品名 | 単価 | 数量 | 合計 |
-----------+------------+------------+------+------+-------
| 00000001 | A001 | 抹茶ケーキ | 200 | 10 | 2000 |
-----------+------------+------------+------+------+-------
| 00000004 | A001 | 抹茶ケーキ | 200 | 25 | 5000 |
-----------+------------+------------+------+------+-------
| 00000003 | A002 | モンブラン | 250 | 8 | 2000 |
-----------+------------+------------+------+------+-------
| 00000002 | B001 | クッキー | 80 | 5 | 400 |
-----------+------------+------------+------+------+-------
| 00000005 | B002 | ビスケット | 70 | 15 | 1050 |
-----------+------------+------------+------+------+-------
| NULL | C001 | マシュマロ | 100 | NULL | NULL |
-----------------------------------------------------------
ORDER BYは、表示順を指定する命令です。
この例では、商品コードの昇順、さらに取引番号の昇順で表示順を指定して
います。
●外部結合の落とし穴
結合条件はON、選択条件はWHEREに書きますが、逆にすることも可能です。
つまり、選択条件をON、結合条件をWHEREに書くこともできます。
結合条件をWHEREに書いた場合、外部結合できないという不便さがあります
ので、あまり使う人はいないのですが、選択条件をONに書いているケースは
比較的目にすることが多いです。
そうしている理由として、結合前に対象レコードを絞り込んでおいた方が実
行速度が速くなるということを挙げられることが多く、データベースの種類
によっては確かに速くなるようです。
SELECT
取引明細.取引番号,
取引明細.商品コード,
商品.商品名,
商品.単価,
取引明細.数量,
商品.単価 * 取引明細.数量 AS 合計
FROM
取引明細 INNER JOIN 商品
ON (取引明細.商品コード = 商品.商品コード
AND 商品.単価 > 100)
ORDER BY
取引明細.取引番号
-----------------------------------------------------------
| 取引番号 | 商品コード | 商品名 | 単価 | 数量 | 合計 |
-----------+------------+------------+------+------+-------
| 00000001 | A001 | 抹茶ケーキ | 200 | 10 | 2000 |
-----------+------------+------------+------+------+-------
| 00000003 | A002 | モンブラン | 250 | 8 | 2000 |
-----------+------------+------------+------+------+-------
| 00000004 | A001 | 抹茶ケーキ | 200 | 25 | 5000 |
-----------------------------------------------------------
この例では、商品単価が100円未満を対象としています。
WHEREに書いても同様の結果が得られます。
では、以下のSQLではどうでしょうか。
SELECT
取引明細.取引番号,
取引明細.商品コード,
商品.商品名,
商品.単価,
取引明細.数量,
商品.単価 * 取引明細.数量 AS 合計
FROM
取引明細 LEFT OUTER JOIN 商品
ON (取引明細.商品コード = 商品.商品コード
AND 商品.単価 > 100)
ORDER BY
取引明細.取引番号
-----------------------------------------------------------
| 取引番号 | 商品コード | 商品名 | 単価 | 数量 | 合計 |
-----------+------------+------------+------+------+-------
| 00000001 | A001 | 抹茶ケーキ | 200 | 10 | 2000 |
-----------+------------+------------+------+------+-------
| 00000002 | B001 | NULL | NULL | 5 | NULL |
-----------+------------+------------+------+------+-------
| 00000003 | A002 | モンブラン | 250 | 8 | 2000 |
-----------+------------+------------+------+------+-------
| 00000004 | A001 | 抹茶ケーキ | 200 | 25 | 5000 |
-----------+------------+------------+------+------+-------
| 00000005 | B002 | NULL | NULL | 15 | NULL |
-----------------------------------------------------------
先ほどとほとんど同じSQLなのに、結果がずいぶん違いますね。
選択条件を書いたはずなのに、結合されてしまっています。
しかもNULLで。
なぜかと言いますと、せっかく選択条件で絞り込んでも、絞り込んだものを
外部結合してしまうのでNULL値として選択されてしまうのです。
選択条件をON、WHEREのどちらに書くかは様々なケースがあるので、どちら
が正しいとは言えませんが、外部結合の際には注意が必要ということを覚え
ておきましょう。
------------------------------------------------------------------------
■編集後記
最後までお読みいただき、ありがとうございました。
最近、ジンバブエ(アフリカ)のニュースをよく見かけます。
失政の影響から極度のインフレが進行し、去年夏までに13桁のデノミを行っ
ているにも関わらず、100兆ジンバブエドルを発行するまでに至りました。
インフレ率は年897垓%という、兆・京の先の単位になっているとも言われ
ておりますが、大体1日でお金の価値が半分になるのだそうです。
昨日100円だったものが、明日になると200円になっているって凄いですね。
なぜそんなお話をしているかと言いますと、2進数の話に近いからです。
1日で倍になるという事は、2進数表記で後ろに0を付けることに等しいで
す。これは凄いスピードで桁が増えていきますね。
こんな話があります。戦国時代に曽呂利新左衛門という武将がおりまして、
恩賞を秀吉からもらう際、将棋の目の数の日数(81日)、お米を今日は1粒
、明日は2粒と倍でもらう約束をしました。
秀吉は欲の無い男だと笑っていたのですが、計算してみると大変なことに。
81日間で渡す米は、なんと2,417,851,639,229,258,349,412,351粒。
慌てて呼び出し、別の報酬に変更してもらったとのこと。
これと同じスピードでインフレが進行しているということで注目されている
のですが、さらにコレラが大発生して相当数の死者が出ていることでも注目
を集めています。
どちらも早く収まるといいですね。
ご感想・ご意見・ご要望などありましたら、気軽にご連絡ください♪
では、また次回お会いしましょう!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
『誰にでもできる!システム開発』 2009/02/02 号
本日のメールマガジンを読んだ感想をお聞かせください。
お寄せいただいた感想は、メールマガジン上で紹介させていただくことが
ありますので、ご了承ください。
配信中止はこちらから↓
http://www.mag2.com/m/0000263428.html
メールアドレスの変更はこちらから↓
http://www.mag2.com/m/0000263428.html
ご意見&ご感想はこちらから↓
http://www.shiga-it-office.com/mailmagazine/ImpressionFrom.html
コンサルティングのご相談はこちらから↓
http://www.shiga-it-office.com/inquiry.html
発行元 志賀IT事務所
http://www.shiga-it-office.com/
関連メールマガジン 「誰にでもできる!インターネット活用術」
http://www.mag2.com/m/0000263426.html
関連ブログ
☆コンサル日和
http://d.hatena.ne.jp/kei_onpu/
☆爆裂!C#野郎
http://csharp.yaminabe.info/
☆10年戦える開発技術
http://10year.yaminabe.info/
☆情報処理技術者試験午前対策
http://am.yaminabe.info/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━



