Получил таблицу людей, которых я хочу связать друг с другом, многие ко многим, с двусторонними ссылками - PullRequest
6 голосов
/ 21 мая 2010

Представьте, что вы живете в очень упрощенном примере - и представьте, что в вашей базе данных MySQL есть таблица людей:

create table person (
    person_id int,
    name text
)

select * from person;

+-------------------------------+
|   person_id |            name |
+-------------------------------+
|           1 |           Alice |
|           2 |             Bob |
|           3 |           Carol |
+-------------------------------+

, и эти люди должны сотрудничать / работать вместе, поэтому вы 'у нас есть таблица ссылок, которая связывает одну запись человека с другой:

create table person__person (
    person__person_id int,
    person_id int,
    other_person_id int
)

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

select * from person__person;

+---------------------+-----------+--------------------+
|   person__person_id | person_id |    other_person_id |
+---------------------+-----------+--------------------+
|                   1 |         1 |                  2 |
|                   2 |         2 |                  1 |
|                   3 |         2 |                  2 |
|                   4 |         3 |                  1 |
+---------------------+-----------+--------------------+

Например, с person__person_id = 4 выше, при просмотре профиля Кэрол (person_id = 3) вы должны увидеть связь с Алисой (person_id = 1)и когда вы просматриваете профиль Алисы, вы должны увидеть отношения с Кэрол, даже если ссылка идет по другому пути.

Я понимаю, что могу выполнять объединение и отдельные запросы, и вообще, чтобы представить отношения как взаимные вUI, но есть ли лучший способ?У меня такое ощущение, что - это лучший способ, когда эта проблема будет аккуратно растаяла при правильной настройке базы данных, но я ее не вижу.У кого-нибудь есть идея получше?

Ответы [ 4 ]

3 голосов
/ 21 мая 2010

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

Поскольку ваша таблица отношений может указывать однонаправленные отношения, я бы посоветовал рассматривать их как таковые. Другими словами, для каждого отношения я бы добавил две строки. Если Алиса сотрудничает с Бобом, таблица должна выглядеть следующим образом:

select * from person__person;
+---------------------+-----------+--------------------+
|   person__person_id | person_id |    other_person_id |
+---------------------+-----------+--------------------+
|                   1 |         1 |                  2 |
|                   2 |         2 |                  1 |
+---------------------+-----------+--------------------+

Причина в том, что во многих системах, подобных ActiveRecord (Rails), табличный объект "многие ко многим" не будет достаточно умным, чтобы запрашивать и person_id, и other_person_id. Сохраняя две строки, объекты ActiveRecord будут работать правильно.

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

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

Эта публикация может оказаться полезной:

http://discuss.joelonsoftware.com/default.asp?design.4.361252.31

После публикации @user вам, как правило, лучше создавать две записи для двухсторонних отношений (Алиса с Бобом и Боб с Алисой в вашемпример).Это делает запросы намного проще и точно отражает отношения.Если у вас есть настоящие однонаправленные отношения, это единственный способ летать.

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

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

  • Одним из способов может быть принудительное выполнение второй записи отношения с использованием триггера вставки
  • затем объявите одну из записей "первичной" (например, ту, где person_id меньше, чем другой _person_id)
  • затем создайте представления и склейте код для своих приложений (выберите, обновите, удалите), которые получают доступ к данным с этими знаниями.
2 голосов
/ 21 мая 2010

Нет лучшей идеи. Реляционные базы данных не могут обеспечить выполнение того, что вы запрашиваете, поэтому вам нужно написать специальный запрос для извлечения данных и триггер для применения ограничения.

Чтобы получить связанных лиц для @person, я бы пошел:

SELECT CASE person_id WHEN @person 
           THEN other_person_id 
          ELSE person_id
       END as related_person_id  
FROM person_person 
WHERE (  person_id=@person 
      OR other_person_id=@person)
...