2009-03-15 4 views
17

すべてCustomerには、物理​​アドレスとオプションの郵送先住所があります。これをモデル化するための好みの方法は何ですか?お客様をモデル化する最善の方法<-->住所

オプション1 Customerはオプション2 Customerは、アドレスタイプ

 
    Customer (id) 
    Address (id, customer_id, address_type, street, city, etc.) 
を記述するためのフィールド が含まれてい Addressに1対多の関係を持ってい Address

 
    Customer (id, phys_address_id, mail_address_id) 
    Address (id, street, city, etc.) 

への外部キーを持っています

オプション3アドレス情報は非正規化され、Customer

に格納されます。
 
    Customer (id, phys_street, phys_city, etc. mail_street, mail_city, etc.) 

私の最も重要な目標の1つは、オブジェクト・リレーショナル・マッピングを単純化することです。そのため、私は最初のアプローチに傾いています。あなたの考えは?

答えて

10

通常の正規化の理由から、私は最初にアプローチする傾向があります。また、この方法では、メーリングリストのデータクレンジングをより簡単に行うことができます。

あなたはおそらく(など、住宅のメール、)複数のアドレスを許可しようとか、効果的な日付を使用することができるよう希望している場合は、多くの場合、

 
    Customer (id, phys_address_id) 
    Cust_address_type (cust_id, mail_address_id, address_type, start_date, end_date) 
    Address (id, street, city, etc.) 
+0

なぜあなたはcust_address_typeとアドレスを全く分けますか?両方に含まれる情報は問題なく1つのテーブルに置くことができます。私は2つのテーブルが3つのテーブルに役立つことはありません。 – JM4

+0

これは、顧客あたり1つ以上の住所を持つことができるためです。請求書、配送なども可能です。また、日付フィールドを使用してeasly履歴を追跡することもできます。同じ住所に複数の顧客を置いて、それぞれをエンティティとして扱うことができますが、住所を変更することで他人に影響を与える必要はありません。 – Karl

+0

また、このモデルは、ほとんどのアドレスのリストがあり、それらを割り当てる状況(たとえば、郵便局などからアドレスリストを購入した場合)に適しています。または、あなたのデータベースが大部分で、あなたの地域でほとんどのアドレスを持つことができる場所。 – Karl

3

2番目のオプションはおそらく私が行く方法でしょう。また、オフチャンスでは、ユーザーは追加アドレスを追加できるようになります(あなたがそのようにしたければ)、船積みなどの意思で切り替えることができます。

3

#1が好きです。良好な正規化を行い、意図を明確に伝えます。このモデルでは、両方のアドレスに同じアドレスオブジェクト(行)を使用することができます。この情報をあまりにも重複して紛失することは、あまりにも簡単です。

+1

これはUIでどのように行われたのか興味があります。私はアドレスオブジェクトを共有することができるシステムを構築しましたが、ユーザーはその概念を理解しませんでした。 – cdonner

+0

私はあなたの説明に基づいて、2番目を意味すると思います。それらはすべて#1でマークされています – singpolyma

+0

@singpolyma No.質問は今でも編集されています。 – krosenvold

1

私は最初のオプションに行きます。このような状況では、私はYAGNIに疲れています(あなたはそれを必要としません)。私は何年もの間、「たっぷり」のテーブルを持っているスキーマを見てきた回数を数えることはできません。 2つだけ必要な場合は、最初のオプションを使用してください。将来要件が変更された場合は、それを変更してください。

1

枚このアプローチを検討してください。それは依存しています。

お客様が複数のアドレスを扱う場合、多対多関係が適切です。あなたは、アドレスが出荷または請求書などのためのものであるかどうかを知らせるフラグをアドレスに導入することができます。あるいは、異なるテーブルに異なるアドレスタイプを格納し、顧客に対して複数の1対1の関係を持ちます。

お客様の住所を知る必要がある場合は、そのto-manyをモデル化する理由は何ですか? 1対1の関係は、ここであなたのニーズを満たすでしょう。

重要:パフォーマンスの問題が発生した場合にのみ、逆正規化を行ってください。

1

オプション3はあまりにも制限があり、オプション1はスキーマを変更せずに他のアドレスタイプを使用できるように拡張できません。 オプション2は明らかに最も柔軟性があり、したがって最良の選択です。

+0

私はそれが最も柔軟であることに同意しますが、ORMの複雑さのトレードオフに値するのですか? –

1

私はあなたが、あなたもアドレスの履歴を維持するためにそれを少し修正することができるしたい場合はオプション1で行くだろう:アドレス変更、ちょうど終了日現在のアドレス場合

Customer (id, phys_address_id, mail_address_id) 
Address (id, customer_id, start_dt, end_dt, street, city, etc.) 

と追加Addressテーブルの新しいレコード。 phys_address_idおよびmail_address_idは、常に現在のアドレスを指します。

あなたはアドレスの履歴を保持することができますこの方法、あなたは(mail_address_idでデフォルトで)データベースに格納された複数のメーリングリストアドレスを持つことができ、かつ物理アドレスとメールアドレスが同一であれば、あなただけのphys_address_idmail_address_idを指します同じレコードで

+0

-1 - この設計では、AddressテーブルとCustomerテーブルの間に双方向の依存関係があるため、データベーススキーマが脆弱になりますが、実際のメリットはありません。 –

6

あなたが問題のドメインに応じて考慮する必要がある重要な事実は、人々がアドレスを変更し、アドレス変更を事前に知らせることです。

この場合、有効期限を持つ顧客の複数の住所を保存する方法が必要です。住所を事前に設定してから自動的に切り替えることができます。正しい点。これが要件である場合、(2)のバリエーションがそれをモデル化する唯一の賢明な方法です。一方

Customer (id, ...) 
Address (id, customer_id, address_type, valid_from, valid_to) 

、あなたはこれに対応するために必要はありません(と、あなたが将来的にではないだろう確信している)場合、それははるかに簡単だから、おそらく(1)管理することが簡単です同じタイプのアドレスが1つしか存在しないことを保証することに問題はないため、データの整合性を維持し、結合は1つのフィールド上にあるので簡単になります。

あなたは家の移動が必要かどうかによって、(1)か(2)のどちらかが良いですが、テーブルの中の住所の定義を繰り返しているので、(3)アドレスがどのように見えるかを変更する場合は、複数の列を追加する必要があります。リレーショナルデータベースで適切に索引付けされたジョインを処理する場合は、得られることはあまりありません。がない場合は、が必要なシナリオでは、処理速度が遅くなる可能性があります顧客のレコードサイズとしてのアドレスが大きくなります。

+0

このアドレステーブルは、顧客の注文していない住所またはオフィスアドレスにのみ関連しています。 – kta

2

これらの質問に答えるときは、私はDDDの分類を使用したいと思います。エンティティの場合は別個のIDを持つ必要があり、値オブジェクトの場合はそうではありません。

2

今日私が書いているほとんどのコードでは、すべての顧客が唯一の物理的な場所を持っています。これはビジネスパートナーの法的実体です。したがって、ストリート、シティなどを顧客のオブジェクト/テーブルに配置します。しばしば、これは動作する可能性のある最も単純なものであり、動作します。

追加の郵送先住所が必要な場合は、顧客オブジェクトをあまり混乱させないように別のオブジェクト/テーブルに入れます。

私のキャリアの初期に、私は配送先住所を参照する顧客を参照する注文があったと怒っていました。これは物事を「きれいに」させましたが、使用するにはゆっくりと控えめでした。今日私はすべての住所情報を含む注文オブジェクトを使用しています。顧客は自分の(デフォルトの)住所を変更する可能性があるので、実際にはこれはより自然なものだと考えていますが、2007年に送信される住所の住所は、2008年に移動した場合でも常に同じにしてください。

現在、VerySimpleAddressProtocol使用されているフィールドを標準化するためのプロジェクトで使用します。

+1

あなたのポイントデータの変更は無効です。単一のアドレス行は、変更してはならないエンティティで参照される場合、変更されないものとする。住所が変更された場合は、新しいレコードを作成しなければならず、既存のものと等しい場合は既存のレコードを使用する必要があります。あなたは歴史を保存しています。ファクタリング企業やeコマース製品でこのアプローチを使用しました。言語依存のルールを使用してユーザーの入力アドレスデータを消去し、非常に優れた比較品質を達成できます。または、郵便会社のような外部プロバイダを使用します。 – djmj

3

私たちは、このようなモデルを進めています:

Person (id, given_name, family_name, title, suffix, birth_date) 
Address (id, culture_id, line1, line2, city, state, zipCode, province, postalCode) 
AddressType (id, descriptiveName) 
PersonAddress (person_id, address_id, addressType_id, activeDates) 

ほとんどこれが過度考えることができます。しかし、私たちが開発するアプリケーションの間で否定できない共通のテーマは、これらの基本的なエンティティ(人、組織、住所、電話番号など)のいくつかを持ち、それらはすべて異なる方法でそれらを結合したいということです。だから、私たちはユースケースを100%確信しているという一般化の前提を構築しています。

Addressテーブルは、階層ごとの継承スキームに従い、カルチャに基づいてアドレスを区別します。米国の住所には州と郵便番号のフィールドがありますが、カナダの住所には州と郵便番号が付きます。

別の接続テーブルを使用して、人にアドレスを「与える」。これにより、私たちの他の事業体 - 人物&は、他の事業体との関係がなくなりました。私たちの経験では、事態が複雑になりがちです。また、アドレスエンティティを他の多くのタイプのエンティティ(人、組織など)に、リンクに関連するさまざまなコンテキスト情報(私の例ではactiveDatesなど)に接続する方がはるかに簡単です。

+0

+1これは私が投稿したデザインです。私はその接続テーブルを使用して多くの機能を駆動してきました。マーケティング・メーラーでさえデータのクレンジング。レポートを欲しがっている人が最後のキャンペーンなどでどこに郵送したのかを見ることができるときに便利です。 – Taptronic

+0

これまではこれが最善の解決策です。 – kta

4

私は、最初に健全な「顧客マスター」デザインであると思われるものが後で壊れることがあることを発見しました。以前は顧客が個々の従業員を顧客として扱うように進化したため、住所をマージする、または事業者が名前を変更するが、以前と新しいパフォーマンスの合計を集計したい場合や、配送先アドレスと請求先住所をサポートアドレスを含めるように拡張する必要がある場合や、お客様が一時的にしか特別な配送先住所を使用したくない場合など

その結果、私はマスター顧客ファイルの考え方を断念するようになりました。その代わりに、名前/会社/住所情報は決してマスターレコードではありません(特定の物理アドレスが決して別の住所に編集可能でない公共料金請求または財産税などのアプリケーションを除く)、それは単に使用中の連絡先を示すフィールドですTIME、通常は受注記録のようなものの中にあります。顧客が名前または住所を変更した場合でも、各受注はその顧客の前後の順序に連鎖されます。利点は、各注文が連絡先の名前または住所を変更する可能性があるにも関わらず、顧客のトランザクション履歴全体にわたってすべての注文を統合/合計/分析できることです。やや直感的ではないですが、特にdbデザイナーを正規化してみてください。しかし、非常に柔軟性があり便利です。

たとえば、顧客Xが最初に注文すると、得意先レコードは登録されません。代わりに、注文時に有効な必要な名前/会社/住所情報を含む受注レコードが作成されます。顧客Xが2番目の注文を行うと、顧客ファイルを検索せずに販売注文ファイルを検索し、それをコピー/チェーンして2番目の受注を作成します。彼が自分の名前/会社/住所情報を変更したいのであれば、私たちは受注#2と受注#1のフィールドをそのまま編集します。現在、彼はいずれかのバリエーション(注文1または2)でロケータ可能です。

その他の考慮事項については

2つの顧客レコードが本当に同じかどうかを判断しようとし、http://semaphorecorp.com/mpdd/mpdd.html

0

グッドスレッドを参照してください。私は最も適したスキーマを検討していますが、私はstart_dateend_dateフィールドをPersonAddressテーブルに追加した以外は、クエンティン・スターリンのソリューションが最高だと結論付けました。私はまた、のノートを追加することを決めました。,アクティブおよびは、を削除しました。

が削除されましたはソフト削除機能用です。ジャンクションテーブルからレコードを削除するだけで、以前のアドレスのトレースを失いたくないと思います。私はそれが非常に賢明であり、他の人が考慮したいと思うかもしれないと思う。このようにしないと、紙や電子文書を改訂してアドレス情報をトレースしようとすることがあります。

ノート私は要件の何かであると思っていますが、それは単に好みかもしれません。私はデータベースのアドレスを検証するバックフィル演習に時間を費やしましたが、いくつかのアドレスは非常に漠然としているかもしれません(田舎の住所など)。私は上の意見を聞きたい

ことの一つは、(再び、クエンティン・スターアンの例では、同じ名前のテーブルを参照するアドレステーブルのユニークインデックスである。あなたはそれが一意のインデックスであるべきだと思いますする必要がありますこれは賢明なように思えるかもしれませんが、郵便番号が単一の財産に対して常にユニークではないにもかかわらず重複データを止めるのは依然として難しいかもしれません。 、州と都市のフィールドに参照データ(モデルに含まれています)が入力されていても、アドレス行のスペルの違いが一致しない可能性があります。入ってくるフォームフィールドを使って重複が見つかったかどうかを確認してください。すでにその人にリンクされているデータベースのアドレスから選択し、それを自動入力することです。私はこれがあなたが賢明になり、重複を止める予防策を講じることができますが、遅かれ早かれそれを受け入れる(そしておそらく)ことができるケースかもしれないと思います。

私のこれ以外の非常に重要な側面は、テーブルレコードのアドレスの将来の編集です。 (異なるエンティティに割り当てられる同じアドレステーブルレコードを可能にするために、危険とみなされるべきではない

11何であれストリート どのような都市 Z1P C0D3

を - :あなたがに記載されている両方の2人を考えてみましょう人、会社)?次に、ユーザーが111 Whatever Streetに住んでいる人のうちの1人を認識し、タイプミスがあるとしましょう。そのアドレスを変更すると、両方のエンティティのアドレスが変更されます。私はそれを避けたいと思います。私の提案は、MVC(私の場合はPHP Yii2)のモデルを既存のアドレスのレコードを探して、その顧客に関連することが知られている新しいアドレスが作成されるときです。 .address_id = address.id WHERE personaddress.person_id = {編集中の現在の人物ID})、代わりにそのレコードを使用するオプションをユーザに提供します(基本的に上記で提案したとおりです)。

は、私はちょうどそれがアドレスレコード(非現実的)の後に編集を拒否した場合であるかもしれないとトラブルを求めたり危険にさらしている複数の異なるエンティティに同じアドレスをリンク感じるそのレコードの将来の編集が破損する可能性があり、データアドレスのレコードを編集中の他のエンティティに関連しています。

私は人々の考えを聞きたいです。

関連する問題