SQL緊急救命室

最終回 更新時合併症~冗長なサブクエリ,性能劣化,実装依存

この記事を読むのに必要な時間:およそ 6.5 分

ここはとある街の総合病院。

ここには通常の診療科のほかに,一風変わった診療科が存在する。

何軒もの病院をたらいまわしにされた,手の施しようのないSQLや,今すぐに改善が必要なSQLが担ぎ込まれる救命室である。

それがSQL緊急救命室,略してSER(SQL Emergency Room)。

そう,ここは国内でも唯一のプログラミング専門外来である。

ロバート
救命室部長。腕の立つエンジニアだが,口が悪く性格はもっと悪い四十オヤジ。

ヘレン
救命室副部長。若いながらもロバートに次ぐ実力を持つ才媛。救命室の良心。

ワイリー
インターンで救命室に配属された不運な学生。無給で治療から雑務全般にこき使われる。エンジニアとしては新人に毛が生えたレベル。

更新における行式

(AM9:00 病院の入り口。ワイリーが扉の前をウロウロしている)

(郵便配達人を見て)あっ! やぁやぁご苦労様。はいはい受け取っておくよ……(郵便物を物色して)うーん違うな。(郵便受けを開けて中を調べる)うーん,ないなぁ。まだかなぁ。

(ロバートが出勤し,ワイリーを見つける)

なんだ,ゴミ拾いにでも転職するつもりか。なんなら推薦状書くぞ。


あっ先生……! 違いますよ。専門課程の合格通知,今日届くんですよ。ああ,どうしよう。ドキドキが止まらない。

倒れたらすぐに献体として使ってやる。それがお前の医学にできる最大の貢献だ。

(聞いていない)ああ,どうしよう。学資ローンもまだ残っているし,これで通らなかったら……。

ふう……まったく。いい加減そのぐらいにして,早く来い!患者が待っているぞ!

更新における冗長なサブクエリ

(治療室。ヘレンがいる。)

遅いじゃないの。先にはじめてたわよ。


すまんな。こいつが道草を食っていたせいでな。……まったく。上の空だな。早く気持ちを切り替えろ。

すいません。どうも不安で。


ああ,そういえば今日だったわね。合格通知。なるほど,そりゃ落ち着かないわけね。でも仕事は仕事よ。

はい。


カルテ1:受発注システムで利用するテーブル「受注明細」図1「発注明細」図2を考える。受注テーブルには顧客から受けた注文の明細が記録される。これをもとに行われる発注処理が「発注明細」テーブルに記録される。今,「発注明細」テーブルに「受注明細」テーブルから品物と数量をコピーする方法を考える図3)。

図1 受注明細テーブル

図1 受注明細テーブル

図2 発注明細テーブル

図2 発注明細テーブル

図3 更新後の発注明細テーブル

図3 更新後の発注明細テーブル

代入式への行式の拡張

患者のコードリスト1は,機能的には間違いじゃありませんよね。

リスト1 患者のコード

UPDATE OrderDetails
   SET item     = (SELECT item
                     FROM EntryDetails AS ED
                    WHERE OrderDetails.entry_id = ED.entry_id
                      AND OrderDetails.entry_seq = ED.entry_seq),
       quantity = (SELECT quantity
                     FROM EntryDetails AS ED
                    WHERE OrderDetails.entry_id = ED.entry_id
                      AND OrderDetails.entry_seq = ED.entry_seq);

間違いじゃないわ。結果は正しく更新されるわ。


ふむ。とすると問題は……。


これまでの治療で見てきた症状を挙げていってみなさい。


ええっと,最初に見たのが「サブクエリ・パラノイア」。でもこのSQLでサブクエリを使わずに解くのは無理ですよね。次が「冗長性症候群」。……たしかに,このSQLはほとんど同じサブクエリを2回繰り返していますね。

このサブクエリは明らかに冗長だな。まあ,まだ1つのSQLで書いているだけこの患者はましなほうだ。ひどいのになるとSQL自体を分割したりするからな。

でもどうやって直すんですか?


前回勉強したでしょう。行式リスト2)。


リスト2 ヘレンの解:行式を利用

UPDATE OrderDetails
   SET (item, quantity)
           = (SELECT item, quantity
                     FROM EntryDetails ED
                    WHERE OrderDetails.entry_id = ED.entry_id
                      AND OrderDetails.entry_seq = ED.entry_seq);

へえ! UPDATE文のSET句でも行式は使えるのですね。


逆に聞くけど,なぜ「使えない」って思った?


いやそれは……。そんないじめないでくださいよ,えへへ。


気色悪い……。


著者プロフィール

ミック

SI企業に勤務するDBエンジニア。主にデータウェアハウス業務に従事している。自身のサイト「リレーショナル・データベースの世界」でデータベースとSQLについての技術情報を公開している。『Web+DB Press』で「SQL緊急救命室」を連載中。

著書:『SQL ゼロからはじめるデータベース操作』(翔泳社,2010)『達人に学ぶ SQL徹底指南書』(翔泳社,2008)訳書:J.セルコ『SQLパズル 第2版』(翔泳社,2007)

Twitter:copinemickmack

SQL緊急救命室:サポートページ

コメント

コメントの記入