Структура MySQL :: Дружба - PullRequest
       4

Структура MySQL :: Дружба

6 голосов
/ 23 октября 2010

Многие люди говорят, что я должен создать таблицу дружбы ( ИД пользователя , friendid ).

Мой вопрос:

Разве не будет двойной записи для каждой дружбы ? как :
12 дружит с 5
+
5 дружит с 12

Есть ли способ предотвратить это ?

| ИЛИ |

Должен ли я просто игнорировать это ?

Ответы [ 3 ]

6 голосов
/ 23 октября 2010

Вы можете использовать как минимум два подхода:

  1. Убедитесь, что userid всегда меньше, чем friendid.
  2. Храните каждое отношение в обоих направлениях (т.е. сохраняйте оба a, b и b, a).

Второй подход стоит вдвое больше памяти и является избыточным, но это означает, что некоторые запросы могут быть намного проще и будут работать лучше. Например, рассмотрите выборку всех общих друзей пользователя 'a' и 'b' с каждым из подходов:

Подход 1:

SELECT friendid
FROM
(
    SELECT friendid FROM friendships WHERE userid = 'a'
    UNION
    SELECT userid FROM friendships WHERE friendid = 'a'
) T1
JOIN
(
    SELECT friendid FROM friendships WHERE userid = 'b'
    UNION
    SELECT userid FROM friendships WHERE friendid = 'b'
) T2
ON T1.friendid = T2.friendid

Подход 2:

SELECT T1.friendid
FROM friendships T1 
JOIN friendships T2
ON T2.userid = 'b' AND T1.friendid = T2.friendid
WHERE T1.userid = 'a'
1 голос
/ 26 октября 2010

Контекст отсутствует, вопрос слишком изолирован, и ответы очень ограничены. Тема не завершена.

Во-первых, для понимания представленная таблица друзей не существует сама по себе. Это дочерний элемент таблицы User с PK UserId. И UserId, и FriendId являются FK для UserId.

Поскольку дружба - это улица с двусторонним движением или двунаправленная (здесь мы исключаем невзаимных любовников и сталкеров!), Тогда в одной строке указывается отношение в обоих направлениях.

Существуют серьезные последствия в именовании любого столбца, поэтому я бы избегал (UserId, FriendId), который подразумевает иерархию или одностороннее отношение, которое является ложным. Я предлагаю (Friend1, Friend2), и, конечно, вам нужен PK, чтобы быть ((Friend1, Friend2).

То, что не было идентифицировано, так это то, что мы до сих пор не предотвратили дубликаты ([5,12] и [12, 5]), та самая избыточность, которую вы хотите предотвратить. Нам нужно правило для обеспечения порядка: Friend1 всегда меньше Friend2.

Существуют и другие отношения, такие как ведомость материалов или родословная, в которой есть сборки и компоненты, для которых требуется нечто большее. Например, (AssemblyId, ComponentId) или (ParentID, ChildId), где это правило не применяется: деталь может быть компонентом в сборке, а также самой сборкой. Это требует двух рядов. Все еще нет дубликатов.

1 голос
/ 23 октября 2010

Я бы спросил: Возможно ли кому-то дружить с собой? Что означает «дружба» - двунаправленная или однонаправленная. Если двунаправленный, то подойдет одна запись, верно? Если однонаправлено, то нужны две записи. Если кто-то не может дружить с самим собой, то вы реализуете бизнес-правило на странице ввода данных (например, на веб-странице, это было бы хорошо для javascript), где идентификатор друга1 <идентификатор друга2 Не уверен, что я согласен с «меньше чем» - они просто не могут быть равными </p>

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