テーブル結合の失敗パターン

RDBMSでのSQLによる問い合わせにおいて、複数のテーブルを結合するパターンは比較的複雑な操作になります。
そのため、ミスも起こりやすいです。

今回は、注意喚起のため、私が実務で出くわしたミスを3つ挙げます。

1.外部結合の結合条件をwhere句に書いてしまい内部結合になってしまう

2.結合条件指定不足で意図せず直積結合してしまう

3.結合条件となる値のセットを誤り結合できなくなってしまう


1.外部結合の結合条件をwhere句に書いてしまい内部結合になってしまう

例えば、以下のようなテーブルがあるとします。

・ログイン日時管理テーブル

・ユーザ名履歴テーブル

ここで、

・ユーザがログインした時のユーザ名を知りたい

・ただし、ユーザがログインした時、ユーザ名が存在しない場合がある

(この場合、ユーザ名が存在していない旨を知りたい)

 

という要件があった場合を考えます。

正しいselect文と問い合わせ結果は以下です。

もし、ここで、誤って結合条件の一部をwhere句に記述すると、下記のようになります。
左側外部結合なのに、左側のテーブルにしか存在しないレコードが抽出されません。

誤ったSQL文については下記①②のような動きになるため、このような結果になります。

① on句に指定された条件で左側外部結合を行う

② ①の結果に対して、where句とselect句が評価される。

(where句で条件指定した場合、内部結合と同じようになる)


2.結合条件指定不足で意図せず直積結合してしまう

例えば、以下のようなテーブルがあるとします。

・社員マスタテーブル

・保有資格管理テーブル

ここで、会社コードが”001″の会社の全社員が保有している資格を取得したいとします。

正しいselect文と問い合わせ結果は以下です。

もし、ここで誤って結合条件に社員コードを含めないと、以下のように実際に保有している資格数よりも多く出力されてしまいます。

なぜこうなるのかは、select文で全カラム指定すればよくわかると思います。
社員マスタテーブル.社員コードと保有資格管理テーブル.社員コードが一致しないレコードについても結合してしまうため、意図せずに直積結合が起こり、実際に保有している資格数よりも多く出力されてしまいます。


3.結合条件となる値のセットを誤り結合できなくなってしまう

例えば、以下のようなテーブルが存在するとします。

・利用料金テーブル

・利用料金明細テーブル

結合する時に指定するキーは利用番号になるため、以下のように利用番号には同一の値を使用する必要があります。

しかし、利用番号がプログラム中で生成する連番であり、かつプログラム中で利用料金テーブルと利用料金明細テーブルで別々に連番を付与していた場合、利用番号で結びつかなくなってしまいます。

こうなると、利用料金テーブルと利用料金明細テーブルを結合するという使い方ができなくなり、後で困ることになります。
更に、既にサービスイン後であり過去データの補正が必要になった場合、その補正も困難になる場合があります。


いかがでしたでしょうか。

今回は失敗パターンの説明ということで、テーブル結合の失敗パターンを取り上げました。
失敗パターンは実務をこなす中で暗黙知的に知ることが多いと思いますので、文章に起こして共有できる形にしていきたいと思います。

カテゴリーSQL

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA