ここはとある街の総合病院。
ここには通常の診療科のほかに,一風変わった診療科が存在する。
何軒もの病院をたらいまわしにされた,手の施しようのないSQLや,今すぐに改善が必要なSQLが担ぎ込まれる救命室である。
それがSQL緊急救命室,略してSER(SQL Emergency Room)。
そう,ここは国内でも唯一のプログラミング専門外来である。
- ロバート
- 救命室部長。腕の立つエンジニアだが,口が悪く性格はもっと悪い四十オヤジ。
- ヘレン
- 救命室副部長。若いながらもロバートに次ぐ実力を持つ才媛。救命室の良心。
- ワイリー
- インターンで救命室に配属された不運な学生。無給で治療から雑務全般にこき使われる。エンジニアとしては新人に毛が生えたレベル。



Keep It Simple, Stupid(シンプルにしておけ,この馬鹿)
―KISSの原則
(AM11:00 休憩室。ワイリーとヘレンが話している)
(写真を見ながら)ほ,ほんとうだ。毛がある。フサフサだ。生まれてからずっとあのいかめしい顔だと思ってたのに!
どんな人間よ,それ。ロバートにだってピーピー泣いてた子ども時代だってあるわ。噂じゃ,若いころはけっこう線が細くて大人しかったそうよ。あなたみたいに。
縁起でもないこと言わないでください。僕は禿げません。絶対に。毎日ちゃんとケアしてますから。
いやー,あなたの髪質細いから案外年とったらロバートみたいに……。
(ロバートが休憩室のドアを開けて首を出す)
おい,ここにいたのか。本日1人目のお客さんが到着したぞ。早く支度しろ。
ああ,はい。エヘヘ。
ウフフ。
なんだ……? 気味の悪い連中だな。人の顔じろじろ見て。
いえ,何でもありません。ささ,早く行きましょ。患者を待たせちゃ失礼ですよ。
SQLで解く方法
これがカルテです。
カルテ1:図1のような2つのテーブルOrders(注文)とOrderReceipts(注文明細)を考える。この2つのテーブルは,お中元の受け付けと配送を管理するためのものです。Ordersテーブルの1レコードが注文1件に対応し,OrderReceiptsはその注文内の商品単位で1レコードになっている。したがって,OrdersとOrderReceiptsは一対多の関係にある。
今,注文ごとに受付日(order_date)と商品の配送予定日(delivery_date)の差を求めて,それが3日以上ある場合は注文者に遅くなる旨の連絡を送りたい。さて,どの注文番号が該当するか,求めてほしい。
レベルの異なる情報を結合する方法
1つの注文に複数の商品が含まれる可能性があるから,OrdersテーブルとOrderReceiptsは一対多の関係になっているわけですね。今,受付日(order_date)と配送予定日(delivery_date)の関係を知りたいのだけど,それぞれ別のテーブルの列だから,結合を使わざるをえないですね。
基本的な考え方はそれでいいわ。結合すれば,商品単位で受付日と配送予定日を表すレコードが得られる。そのあとはどうするかしら?
あとは,受付日と配送予定日の差を求めればいいから……(リスト1)。あれ,エラーになった。
リスト2 ワイリーの解:WHERE句に間違いあり
SELECT O.order_id,
O.order_name,
ORC.delivery_date - O.order_date AS diff_days
FROM Orders O
INNER JOIN OrderReceipts ORC
ON O.order_id = ORC.order_id
WHERE diff_days >= 3; ― エラーの原因
列"diff_days" は存在しません。行 7: WHERE diff_
days >= 3;(注1)
……。
おっかしいなあ。このDBMSバグってませんか?
思い通りにいかないと道具のせいにするのは素人の常だが,現実にはプログラマの頭がバグっている可能性のほうがはるかに高い。これは統計学的に証明されている。疑うのなら自分の頭を先に疑え。
- 注1)
- このエラーメッセージはPostgreSQLのものですが,ほかのDBMSでもこのSELECT文は同様のエラーになります。



