生島 勘富SQL講座

きっとそのうちはてなダイアリーに詳細が上がるのではと。彼の言う「ばっちくないテーブル設計」というのの詳細説明はいつあるのだろうか。@ITにも結局詳述なかったようだし。
0
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

@naka_aki_spl O/Rマッパはミスマッチを超えるためにあるので、どこまで行ってもRDBの構造を引きずってしまいますから、オブジェクト指向と呼ぶならテーブルと一対一のパターンだけじゃないかと思ったり。

2010-06-02 16:23:27
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

SQLが書けないというのは、FROM句、WHERE句が分かってないということ一番の理由。FROM句、WHERE句が書けるようになれば、後は枝葉末節です。

2010-06-02 19:48:57
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

サンプルは売上ヘッダ・売上明細・得意先マスタ・商品マスタがあるとします。商品には「雑品」としてコードが与えられてないモノがあるとします。

2010-06-02 19:50:39
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

余談ですが、顧客が「『雑品』としてコードがないモノがある」といっても、それを真に受けて設計するのは良くない。顧客は裏で自動登録されているかどうかは知ったことではない。「これを顧客の要望です!」ってやるから、テーブル構造が汚くなる。

2010-06-02 19:53:50
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

自動登録してもインデックスが当たる形になっていたら、その方がパフォーマンスが良くなる。最悪、ID:999999 雑品 としてマスタ登録する方がよい。RDBはリレーションしないデータがあると、あちこちで不都合が起きる。

2010-06-02 19:55:58
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

それはともかく、JOINの特徴。つなぐ相手がユニークでなければ返されるレコードが増えます。ですから、同じレコードが出力されるときは、ほぼ、FROM句(JOIN)にバグがあります。DISTINCTで逃げないようにね(苦笑)

2010-06-02 19:57:37
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

まず最初に、ループの基礎になるテーブルを考えます。手続き型の言語では対象レコードが多い(つまりトランザクション)をメインループに選ぶことが多いでしょう。SQLは似ていますが、最終的に欲しい件数が入っているテーブルと考えてください。

2010-06-02 19:59:37
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

今回は売上ヘッダ・売上明細をメインループに選びます。私は無意識にやっていたけれど、主キーどうして繋がる所まで(サロゲートキーを使わず、複合キーの場合)はメインループと考えてください。

2010-06-02 20:01:43
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

売上ヘッダ.伝票番号(主キー)= 売上明細.伝票番号(主キーの一部)となるところまでがメインループで基本的にINNER JOINでつなぐ。ここで外部結合を使う必要があるとしたらテーブル設計を見直そう。どっかおかしい。

2010-06-02 20:03:19
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

次に、参照整合性がついている、NOT NULL制約があるカラムとマスタに対しては、INNER JOINでつなぎます。

2010-06-02 20:05:38
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

その後、NULLが入ったりするカラムと結合します。そのNULLのレコードを抽出したいとき、LEFT (OUTER) JOIN で結合します。

2010-06-02 20:08:33
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

LEFT (OUTER) JOIN はベン図の左側の円がまん丸で、右側が欠ける結合。RIGHT (OUTER) JOIN はその逆。SQLは一行で書けるので、左側のテーブルが円がまん丸。のイメージを持ち続けること。

2010-06-02 20:10:44
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

「無条件でLEFT JOINにする」「LEFT JOINにしないとデータが出ないときがある」とかいう人もあるけれど、本来は闇雲に使うべきではありません。

2010-06-02 20:13:02
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

LEFT JOINの間違った例 http://codepad.org/qk8OvmOh 正しくはこちら http://codepad.org/aYJimXh4 商品マスタをLEFT JOINする必要はないはずですが、LEFT JOINにするところが多いですね。

2010-06-02 20:17:24
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

なぜ間違いかというと、LEFT JOINを選択しているということは、「商品マスタにない売上明細も出力したい」という意思表示です。

2010-06-02 20:19:39
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

ところが、「商品マスタにない売上明細」に紐付くカラムはすべてNULLになっています。つまり、WHERE句の「s.商品種別 = 'Z'」は「NULL = 'Z'」つまり FALSE になりますので出力されません。

2010-06-02 20:21:51
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

ベン図の欠けた方に抽出条件を書くと出力されなくなって、INNER JOINと同じ結果になると覚えても良いでしょう。

2010-06-02 20:24:03
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

LEFT JOINの間違った例 http://codepad.org/qk8OvmOh を見て直感的に気持ち悪い。と思わないと潜在バグを量産しているかも知れません。

2010-06-02 20:25:24
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

冗談抜きで、数億規模の案件で 例 http://codepad.org/qk8OvmOh のようになっているものが、数千ってこともあった。そのうち数10%がバグで、他はINNER JOINでも良かったもの。

2010-06-02 20:28:56
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

これをやられると、ソースだけでは業務上バグなのか、バグでないのか分かりません。

2010-06-02 20:32:27
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

間違えないためには、抽出条件なのか、結合条件なのか考えれば良いのですが、ベン図で考えてもいいですし、LEFT JOINでつないだテーブルのカラムはWHERE句に入れてはいけないと覚えても良い。

2010-06-02 20:32:59
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

しかし、丸暗記より、これまでの内容をイメージする方が身につくと思う。

2010-06-02 20:33:19
SQLの苦手を克服する本(技術評論社)/生島 勘富 @Sikushima

ちなみに、商品マスタがメインループになる場合はどんな場合でしょう。それは、また明日 ノシ~

2010-06-02 20:33:43
1 ・・ 5 次へ