Каковы подходящие способы представления отношений между людьми в таблице базы данных? - PullRequest
4 голосов
/ 01 мая 2010

У меня есть таблица людей - первичный ключ ID и имя. В моем приложении люди могут иметь 0 или более реальных отношений с другими людьми, так что Джек может «работать на» Джейн и Том может «заменить» Тони, а Боб может «быть сотрудником« Роб и Боб могут также »быть женаты на "Мэри.

Какой лучший способ представить это в базе данных? Много-много пересекаются таблицы? А серия само присоединяется? Таблица отношений с одной строкой для каждой пары отношений и типа, куда я вставляю записи для отношения в обоих направлениях?

Ответы [ 6 ]

3 голосов
/ 10 июня 2016

Я знаю, что это старая тема, но все еще актуальна.

Допустим, Мэри и Джон женаты и имеют двоих детей, Джейн и Мэтта ...

А как насчет этой структуры таблицы:

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

Когда нам интересно найти родственников одного человека, мы можем выполнить 2 запроса, ища этого человека в столбце side1, а затем в столбце side2 ...

Или, может быть, один запрос ищет этого человека в том или ином столбце, чем мы используем логику в нашем приложении и:

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)  

Джейн (ребенок)
Мэтт (ребенок)

2 голосов
/ 01 мая 2010

Создайте отдельную таблицу «многие ко многим» для каждого типа отношений.

Если вы попытаетесь представить несколько типов отношений в одной таблице «многие ко многим», это будет нарушением Четвертой нормальной формы .


Комментарии:

На самом деле нарушение 4NF будет выглядеть примерно так:

Person1 Person2 Is_Employer Is_Teacher Is_Father
Tom     John     No          No         Yes

Если у вас есть таблица из трех столбцов, в которой перечислены два человека и тип отношений, это лучше, но у вас все еще есть проблема с взаимными отношениями.

Person1 Person2  Rel_type
John     Ann     married

Некоторые люди не понимают, следует ли хранить две строки или же хранить двух людей в каком-то последовательном порядке (например, сначала нужно меньшее значение идентификатора). Но тогда есть отношения, которые направлены, как «работодатель», где порядок что-то значит. И есть отношения с несколькими людьми, как «братья и сестры».

Таким образом, другим способом организации этих отношений было бы создание таблицы со списком групп, по одной группе на строку, а затем еще одна таблица со списком людей в этой группе.

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

Это лучше всего подходит для отношений, которые имеют переменное число членов и являются взаимными отношениями. Члены спортивной команды - еще один пример. По сути, это таблица «многие ко многим» между группой и людьми.

Вам может понадобиться несколько способов хранения отношений для учета всех различных типов.

1 голос
/ 02 мая 2010

убедитесь, что вы включили даты в таблицу ссылок. поскольку отношения не вечны ...

**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
0 голосов
/ 04 мая 2010

@ Билл К:

"Если у вас есть таблица из трех столбцов, в которой перечислены два человека и тип отношений, это лучше, но у вас все еще есть проблема с взаимными отношениями."

Не страдает ли решение, которое вы впервые предложили (одна таблица для каждого типа отношений) от той же самой проблемы?

Кстати, ваш термин («взаимный») неверен, imo. Вы говорите об отношениях (в математическом смысле), которые имеют свойство симметричный . Насколько мне известно, область, оставленная теорией, ответила очень неудовлетворительно.

Вариант с тремя колонками - это то, как это было сделано в моем самом первом проекте, почти 30 лет назад, и я верю, что он все еще является наилучшим из возможных подходов. Тем более что «возможный / релевантный набор типов межличностных отношений», eurhm, является довольно изменчивой вещью в любом бизнесе, который я могу себе представить.

0 голосов
/ 01 мая 2010

Я недавно столкнулся с этой ситуацией, и после того, как опробовал пару различных вариантов, получилось что-то вроде этого (простите за модель псевдокода):

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

class RelationshipMember {
    int Id;
    Person RelatedPerson;
}

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

Вы можете поместить свойства в Relationship, чтобы смоделировать его тип, а свойства - в RelationshipMember, чтобы смоделировать роль в отношении, если это необходимо.

И, конечно же, это допускает тройки. :)

В этом конкретном проекте я использую инструмент ORM ( nHibernate с 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
)
0 голосов
/ 01 мая 2010

Вы можете создать таблицу со следующей структурой,

person1, relation, person2

теперь, когда в него вставляются значения, например, если Джон - муж Келли, тогда

john, is husband of, kelly

и применять то же самое для Келли

kelly, is wife of, john

Вам нужно будет определить отношения для обоих людей, но это принесет хороший результат при получении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...