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

Предположите, что Вы живете на очень упрощенной земле в качестве примера - и предполагаете, что у Вас есть таблица людей в Вашей базе данных 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
)

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

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_id = 4 выше при просмотре Carol (person_id = 3) профиль необходимо видеть отношения с Alice (person_id = 1) и когда Вы посмотрели профиль Alice, необходимо видеть отношения с Carol, даже при том, что ссылка идет другим путем.

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

6
задан lexu 21 May 2010 в 06:06
поделиться

4 ответа

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

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

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, будут работать правильно.

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

3
ответ дан 10 December 2019 в 02:43
поделиться

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

Чтобы получить связанных лиц для @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)
2
ответ дан 10 December 2019 в 02:43
поделиться

Вы должны найти этот пост полезным:

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

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

2
ответ дан 10 December 2019 в 02:43
поделиться

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

  • Одним из способов может быть принудительное выполнение второй записи отношения с помощью триггера вставки
  • , затем объявление одной из записей «первичной» (например, той, где person_id меньше, чем другой _person_id)
  • , затем построение представлений и склеить код для ваших приложений (выбрать, обновить, удалить), которые получают доступ к данным с этими знаниями.
2
ответ дан 10 December 2019 в 02:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: