4

私は人のテーブルを持っています - ID 主キーと名前。私のアプリケーションでは、人々は他の人々と0以上の現実世界の関係を持つことができるので、ジャックはジェーンのために「働き」、トムはトニーに「取って代わり」、ボブは「ロブの従業員であり、ボブは結婚しているかもしれません」 「メアリーへ。

これをデータベースで表現する最良の方法は何ですか? 多対多の交差テーブル? 一連の自己結合? リレーションシップ ペアとタイプごとに 1 行のリレーションシップ テーブルに、リレーションシップのレコードを両方向に挿入しますか?

4

6 に答える 6

4

関係のタイプごとに個別の多対多テーブルを作成します。

1つの多対多のテーブルで複数のタイプの関係を表現しようとすると、第4正規形に違反します。


コメントについて:

実際、4NFの違反は次のようになります。

Person1 Person2 Is_Employer Is_Teacher Is_Father
Tom     John     No          No         Yes

2人と関係タイプをリストする3列のテーブルがある場合は、それが優れていますが、相互関係には問題があります。

Person1 Person2  Rel_type
John     Ann     married

2つの行を格納するのか、それともある種の一貫した順序で2つの行を格納するのか(たとえば、ID値を最初に低くするなど)について混乱する人もいます。しかし、順序が何かを意味する「雇用者」のように、指示された関係があります。そして、「兄弟」のように、複数の人との関係があります。

したがって、これらの関係を整理する別の方法は、グループを一覧表示するテーブルを作成し、行ごとに1つのグループを作成してから、そのグループ内の人々を一覧表示する別のテーブルを作成することです。

Group Rel_type    Group Person
123   siblings    123   Bobby
                  123   Peter
                  123   Greg
                  123   Cindy
                  123   Jan
                  123   Marsha

これは、メンバーの数が可変で、相互関係である関係に最適です。スポーツチームのメンバーは別の例です。それは本質的に、グループと人々の間の多対多のテーブルです。

すべての異なるタイプを説明するために、関係を保存するための複数の方法が必要になる場合があります。

于 2010-05-01T18:52:27.673 に答える
3

私はそれが古いスレッドであることを知っていますが、まだ関連しています。

メアリーとジョンが結婚していて、ジェーンとマットの 2 人の子供がいるとしましょう...

このテーブル構造はどうですか:

side1    | side1type    | side2type    | side2
----------------------------------------------------
Mary     | wife         | husband      | John
Jane     | child        | mother       | Mary
Jane     | child        | father       | John
Matt     | child        | mother       | Mary
Matt     | child        | father       | John 
Jane     | sister       | brother      | Matt

1 人の親戚を見つけたい場合、列 side1 でその人を検索し、次に列 side2 でその人を検索する 2 つのクエリを実行できます...

または、アプリケーションでロジックを使用するよりも、1 つまたは別の列でその人を探す 1 つのクエリで、次のようになります。

If that person has been found in side1 column 
   we print side1, side1type, "of ", side2  

メアリーはジョンの妻

If that person has been found in side2 column 
   we print side2, side2type, "of ", side1  

メアリーはジェーンの母
メアリーはマットの母

それとももっとエレガント...

If that person has been found in side1 column 
   we print side2 (side2type)  

ジョン(夫)

If that person has been found in side2 column 
   we print side1 (side1type)  

ジェーン(子供)
マット(子供)

于 2016-06-10T07:07:20.747 に答える
1

リンクテーブルに日付が含まれていることを確認してください。関係は永遠に続くわけではないので...

**person**
person_id
name

**person_person**
person_id_1
person_id_2
relationship_type_id
begin_date
end_date

**relationship_type**
relationship_type_id
name
于 2010-05-02T14:03:27.633 に答える
0

次の構造でテーブルを設計できます。

person1, relation, person2

たとえば、値を挿入すると、ジョンがケリーの夫である場合、

john, is husband of, kelly

ケリーにも同じように塗る

kelly, is wife of, john

両方の人の関係を定義する必要がありますが、フェッチ中に良い結果が得られます。

于 2010-05-01T18:55:02.410 に答える
0

私は最近この状況に遭遇し、いくつかの異なるオプションを試した後、次のような結果になりました(疑似コードモデルを許してください):

class Person {
    int Id;
    List<RelationshipMember> Relationships;
}

class RelationshipMember {
    int Id;
    Person RelatedPerson;
}

class Relationship {
    int Id;
    List<RelationShipMember> RelationshipMembers;
}

Relationship にプロパティを配置してそのタイプをモデル化し、RelationshipMember にプロパティを配置して、必要に応じて関係内のロールをモデル化できます。

もちろん、3Pも可能です。:)

この特定のプロジェクトでは、ORM ツール ( nHibernate with Fluent Automapping ) を使用しています。データベース テーブルの表現方法は次のとおりです。

TABLE Person (
   Id int NOT NULL
)

TABLE Relationship (
   Id int NOT NULL
)

TABLE RelationshipMember(
Id int NOT NULL,
Relationship_id int NOT NULL,
    Person_id int NOT NULL
)
于 2010-05-01T19:10:14.457 に答える
0

@ビルK:

「2 人の人物と 1 つの関係タイプをリストする 3 列のテーブルがある場合は、そのほうがよいのですが、それでも相互関係には問題があります。」

あなたが最初に提案した解決策(関係タイプごとに1つのテーブル)は、まったく同じ問題に悩まされていませんか?

ところで、あなたの用語(「相互」)は間違っています、imo。あなたは対称であるという性質を持つ関係(数学的な意味)について話している. 私の知る限り、理論が残した領域は非常に不十分な回答しか得られませんでした。

3 列のオプションは、ほぼ 30 年前の私の最初のプロジェクトで行われた方法であり、今でも可能な最良のアプローチであると信じています。特に、「可能な/関連する対人関係タイプのセット」は、ええと、私が想像できるあらゆるビジネスにおいてかなり不安定な種類のものです.

于 2010-05-03T20:26:25.143 に答える