web-dev-qa-db-ja.com

「都市」は別の表に値しますか?

次のCustomersテーブルがあります。

customer_id - int 
company_name - nvarchar
street - nvarchar
city - nvarchar
comments - nvarchar

アプリは1つの小さな国(30都市など)の一部でのみ使用されます。友人から、「city」を別のテーブル「Cities」に分離し、customersテーブルではcity_idのみを使用するように言われました。

個人的には、それによるメリットはあまりありませんでした(ただし、この場合、別のテーブルを作成するコストの点で、私にとっては重要ではないように見えるCustomersテーブルのスペースを節約する場合を除く)。

彼はまた、重複した列があるため、city:foo、city:bar、city:fooと述べました。 (同じ都市の少数の顧客)これは正規化されているとは見なされませんが、本当ですか?

誰が正しいのですか?この問題に関する啓蒙?

4
BornToCode

デザインは 第3正規形 を満たしていませんが、都市のためではありません。フィールドSTREET、CITYは機能的に互いに依存しています(都市を変更すると、ストリートもおそらく変更されます)。同じ通り、都市の組み合わせをさまざまな方法で表すこともできます(Foo St、Foo、Foo Street、Fooなど)。

これを正規化するには、通り、都市などを含む新しいテーブルADDRESSESを作成し、住所IDを介して顧客をそれにリンクします。また、これが必要な場合は、リンクテーブルを介して顧客の複数の住所をリストすることもできます。

これでも、都市を独自のテーブルに抽出するかどうかを決定する必要があります。 3NFを完全に満たすには、次の質問に対する答えに応じて、必要かどうかによって都市テーブルを作成する必要があります。

  1. あなたは(またはあなたは)都市の追加の属性を持っていますか(例:人口、郡/州、表示名など)
  2. クエリを実行して、選択する個別の都市のリストを生成していますか(コメントは「はい」を示唆しています)

最初のポイントがtrueの場合は、必ずCITIESテーブルを作成する必要があります。そうしないと、人口が異なる1つの都市になる可能性があります。2番目のポイントがtrueの場合は、リストするクエリとして別のテーブルを作成することをお勧めします。すべての都市のスケーリングが大幅に向上します-(ほぼ確実に大きい)CUSTOMERSテーブルではなく、このテーブルをスキャンして、そこから異なる都市を取得するだけで済みます。

5
Chris Saxon

それに入るときreally入る-コンポーネント化されたアドレスデータを格納することは、世界中で使用されているすべての異種の多様なシステムのため、非常に複雑な問題です。

開発するものは何でも、柔軟性とyourビジネスが保存する必要があるものだけを保存することの間でバランスを取る必要があると思います。


ここでのパズルの最大のピースは、アドレス関連のすべてのフィールドをCustomersテーブルから移動することです。アドレスはそれ自体のエンティティです。

スペースコストは、非常に小さなシステム(おそらく)には関係ないかもしれませんが、これは技術的な負債の問題に関するものです。アドレス関連のフィールドをさらに追加する必要がある場合は、Customersテーブルにフィールドを追加していく必要があります。遅かれ早かれ、これは柔軟性のない設計であることに気づくでしょう-特定の顧客に対して複数の住所を使用する必要がある場合(請求先住所と配送先住所は典型的な例です)、今では正規化せずに傷ついた世界にいます既存の構造を再利用して必要なデータを保存することはできないためです。

絶対に、新しいテーブルAddressesを作成してから、Customersからaddress_idを参照します。最終的に複数のアドレスルートに行きたい場合は、(現在のデザインに固執するのではなく)このステップだけでも、後で大きな頭痛の種を節約できます。

住所行は、単純にするためにAddressesテーブルに直接入れることも、複数の行を処理するために別のAddress_Linesテーブルに入れることもできます。 (通常は後者が推奨されます。)

その後、意味のある方法でデータをスライスおよびダイシングできるようにするための一般的な最小値は、正規化されたCountriesRegions(別名、州/領土など)、およびCitiesテーブル。後者のみがAddressesテーブルのフィールドとして表示されます。これにより、「市Xで何製品を販売したか」などのビジネス上の質問をすることができます。 and「地域Yで販売した製品の数」 (注:操作する場所、データ、スライス方法によっては、RegionsCitiesの間に4番目のテーブルが必要になる場合があります。)

もっと細かくする必要がある場合(「ストリートXの顧客に何製品を販売したか?」)、住所行自体のコンポーネント化を開始する必要がありますが、これは本当に難しい部分です。しかし、通常、企業はこの種の質問をしません。郵便番号フィールドも表示されていないことを考えると、これはあなたが気にするものではないと思います。

6
Jon Seigel

アドレスモデリングは普遍的ではありません。普遍的な実装は、ほとんどのアプリケーションにとって複雑すぎます。さまざまなモデルは、モデルタイプ(OLTPとOLAP)、国のルール、顧客タイプ(組織と個人)、住所データの重要度などによって異なります。

言われたように、あなたは都市を分離するべきです。 Cityを分離すると、customerテーブルの異なる都市名がなくなるという問題がなくなります。理由は次のとおりです。

1-別のテーブルで都市名を分離すると、次のようなクエリを実行できます。顧客を都市別に分布させ、顧客がいない都市を表示する。

2-GUIが常に都市の正しいリストを参照できるようにします。

3-プログラムコードに触れずに都市情報を維持できます。

4-以下の図を使用すると、(異なる州の)都市名の重複を許可します。

アプリケーションが1か国向けであることが確実な場合は、国を追加しないでください。

また、北アメリカで一般的な通りの住所情報を2列に分けておらず、郵便番号がないことに気づきました。国の郵便当局からの住所要件を確認して、設計がそれらに準拠していることを確認してください。

OLTPアプリケーションでの住所の一般的な表現を次に示します。CityのPKは、CityIDとStateIDの2つの列です。このバージョンのバリエーションは、各テーブルに単一のIDを使用することです。 (シーケンス番号として)、顧客テーブルでのみ1列で構成されるFKになります。

すべては、ビジネスルールと要件に要約されます。

enter image description here

以下は基本的な表現です。

2
NoChance

デザインを正規化するには、CITYを分離する必要があります。省スペースに加えて、その優れたデザイン。また、Foo、foo、Foooなどの重複する都市名エントリを軽減し、郵便番号のようにそのテーブルに都市固有の詳細を含めることができます。

1
Shiva