質問: こちらの「NULL排除について」の質問について拝見していました。 しかし書かれていることについて理解があまり進まず分からない点があったので質問致します。 質問者の現状のDB構成は以下だということは分かりました。 (Modelは回答者の例から店舗と置き換えています) DB --- 店舗(model)モデル | id | prefecture_id | city_id | | --- | --- | --- | | 1 | 1 | 1 | 都道府県(Prefecture)モデル | id | prefecture | ~~~ | | --- | --- | --- | | 1 | 東京都 | ~~ | 市区町村(City)モデル | id | city | ~~~ | | --- | --- | --- | | 1 | 奥多摩町 | ~~ | 都道府県中間 | id | model_id | prefecture_id | | --- | --- | --- | | 1 | 1 | 1 | 市区町村中間 | id | model_id | city_id | | --- | --- | --- | | 1 | 1 | 1 | 質問点 ---- ### 何故1対1の関係を使っているのか 質問者の質問によると > > Modelと Prefecture Cityは一対一の関係です。 > > > とあります。 しかしここで都道府県と市区町村というデータが保存されている、ということは 都道府県と店舗で言うと「1対多」と自分は感じましたが間違っているのでしょうか? 「「東京都」はたくさんの「店舗」を持てる」というように考えると1対1ではないような気がしました。 1対1ということは例えば「東京都」というレコードが複数存在する可能性があるということでしょうか? ### Unknownレコード追加とは? 回答者のmiyabi-sunさんから解決策が提案されています。 > > まずはPrefectureとCityのマスターテーブルに「見当たらなかった」用のUnknownレコードを追加しよう。 > > > ここで言う「Unknownレコード」追加の解決法とは * 都道府県モデルで言うと、prefectureカラムにunknownというデータを挿入。 * 店舗モデルで都道府県が表記ゆれ等で適切な外部キーが引けなかった場合は、挿入したunknownのidを外部キーとする(これで中間テーブルの存在は要らなくなる) という認識で合ってるでしょうか? ### 店舗モデルはどういった設計をイメージしているのか? 最後にこちらの質問者が作成しているDB設計についてです。 そもそもの設計として「店舗モデルに住所をCSVからインポートする」ということは、DBとしては | id | address | prefecture_id | city_id | | --- | --- | --- | --- | | 1 | 東京都足立区~~~ | 1 | 1 | | 2 | 東京都千代田区~~~ | 1 | 2 | | 3 | とうきょと足立区~~~ | 1 | 1 | こういう設計になっているということでしょうか? 自分自身CSVからインポートするという経験がないのであまりイメージできていません。 CSVからインポートする際にprefectureやcityテーブルを参照して一致したら外部キーのidを書き込む、という方法なのでしょうか? 以上の3点がこちらの質問を拝見させていただいて分からない点でした。 どなたか教えて頂ける方いらっしゃいましたら教えていただきたいです。 よろしくお願いします。
回答: RoRから離れたデータベースの観点で、システムのDB構成を見ると 理解、そして誤解点の修正ができると思います。 なおRoR自体はあまり詳しくないので、その点はご理解ください。 ### 回答 > > 「「東京都」はたくさんの「店舗」を持てる」というように考えると1対1ではない > > > この認識は正しくないです。現実に**「店舗」は1つの住所しか持たない**ので、 1つの「都道府県」データと1つの「市区町村」データで 住所を示せます、1つですみます。 ですから**「1対1」の関係**なのです。 ですので > > 1対1ということは例えば「東京都」というレコードが複数存在する可能性があるということでしょうか? > > > とはなりません。 あくまで都道府県(Prefecture)モデルが主語であり、どういう項目を持つのかがポイントです。 都道府県(Prefecture)モデルはたくさんの「都道府県」データを持てるのです。 (実際には北海道から沖縄県までですが) そして「東京都」は都道府県(Prefecture)モデルの**データの1つ**です。 都道府県(Prefecture)モデル、市区町村(City)モデルともに、「東京都」は1つだけ、また青梅市も世田谷区もそれぞれ1つだけモデルに存在することになります(現実世界でもそうなっていますね)。 ### Unknownレコード追加とは? > > 都道府県モデルで言うと、prefectureカラムにunknownというデータを挿入。 > > > これは不明なprefectureそのもののデータを追加することです。 たとえば 47 沖縄県 ~~ の後に 「48 東京県 ~~」 と追加idを付加し、追加します。 ### 店舗モデルはどういった設計をイメージしているのか? これはわかりません。元の設計者の考えを聞くか、ここで公開していただくしかないですね。 ただ > > CSVからインポートする際にprefectureやcityテーブルを参照して一致したら外部キーのidを書き込む、という方法なのでしょうか? > > > これは厳密な意味では間違いです。インポート作業はデータを流し込むだけです。 ただしインポートの前処理でありえない誤データの削除や、重複行を排除する作業をします。 テーブル(マスター管理テーブル)では、prefectureやcityテーブルを参照して一致したら・・・の処理は現実にはします (もしマスターテーブルで ゆれがあると、これを参照する画面要素、リストボックスの表示に影響がでる、などありますからね)。 ### 「リレーションシップ」に関しての詳しい解説 このモデルは、DBシステムにおけるテーブルなどのスキーマ定義の元データです。 で、実行結果できるDBのテーブル(テーブルそのもの)は、各モデルが元になると思います。 そうなると、普通にDB理論におけるER図、 「エンティティとリレーションシップ」の考え方で通用すると考えます。 そして**質問者の方の疑問点は、ずばり「リレーションシップ」の捉え方、 認識が設計者と違う**ということになります。 本題の > > 都道府県と市区町村というデータが保存されている、ということは > > 都道府県と店舗で言うと「1対多」と自分は感じましたが間違っているのことなるでしょうか? > > 「「東京都」はたくさんの「店舗」を持てる」というように考えると1対1ではないような気がしました。 > > > 1対1ということは例えば「東京都」というレコードが複数存在する可能性があるということでしょうか? > > > 一般的なDBでの現実の世界からの「エンティティとリレーションシップ」の洗い出し法を元に、3つのモデルを見るといいです。 実際にはこんな感じで抽出していきます(関係ある一部のみ、書きます) 1.店舗(model)モデル、都道府県(Prefecture)モデル、市区町村(City)モデルが扱うエンティティ(モデル)があって、それぞれは属性を持つ、(以下、省略) **2.店舗(model)モデルは1つの都道府県(Prefecture)モデルを所有する(=のみ所有する)** **3.店舗(model)モデルは1つの市区町村(City)モデルを所有する(=のみ所有する)** ここで太字にした箇所が誤解されている、異なる点ですね。 いずれも「1対1」です。 2.「「東京都」はたくさんの「店舗」を持てる」ではなく、(主体である)「店舗」は 現実には1つの住所しかもたないわけですから店舗モデルには1つの都道府県モデルが存在する。 3.同じように店舗は1つの区や市町村に属します。店舗モデルには1つの市区町村モデルが存在する。