Хранение отношений в базе данных MySQL - PullRequest
0 голосов
/ 06 февраля 2011

Я создаю отношения «многие ко многим» между контентом, но для упрощения я пока воспользуюсь более простыми отношениями.Примером могут служить отношения между фильмами.Как правильно хранить эти данные?

Я изначально делал это:

Movie | Related Movie | Relation (Relation of the related movie)
--------------------------------
Matrix   | Matrix 2 | Sequel
Matrix 2 | Matrix   | Prequel

Итак, Matrix 2 - это продолжение Matrix, но потом я понял, что это не похожеимеет смысл хранить отношение родственного фильма вместо отношения фактического фильма.Тогда я попробовал это вместо этого:

Movie | Relation | Related Movie 
--------------------------------
Matrix   | Prequel | Matrix 2
Matrix 2 | Sequel  | Matrix

Теперь я сохраняю фактическую связь фильма вместо связанного фильма, так что строка имеет больше смысла.Это также более буквально, Matrix является приквелом Matrix 2.

Однако тогда я понял, что во внешнем интерфейсе 2-й способ будет выглядеть так для страницы Matrix: Prequel - Matrix 2

И для страницы Матрица 2: Сиквел - Матрица

Таким образом, первый способ, по-видимому, более правильно хранит данные в бэкэнде, но не во внешнем интерфейсе.И второй способ, по-видимому, заключается в том, что он неправильно хранит данные в бэкэнде, но во внешнем интерфейсе это имеет больше смысла.

Так что в этом случае я должен на самом деле хранить данные наоборот (2-й способ)Должен ли я вообще беспокоиться об этом?Пока это имеет смысл в переднем конце?

1 Ответ

0 голосов
/ 06 февраля 2011

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

Например, почему бы не сделать:

SELECT * FROM movies;
+----+---------------+
| id | title         |
+----+---------------+
|  1 | Matrix        |
|  2 | Matrix 2      |
|  3 | The Animatrix |
+----+---------------+

SELECT * FROM movie_relations;
+----+----------+---------------+------------------+
| id | movie_id | relation_type | related_movie_id |
+----+----------+---------------+------------------+
|  1 |        1 | sequel        |                2 |
|  2 |        1 | offshoot      |                3 |
|  3 |        2 | offshoot      |                3 |
+----+----------+---------------+------------------+

Теперь, если вам нужно найти все продолжения Matrix:

SELECT related_movie_id FROM movie_relations 
WHERE movie_id = 1 AND relation_type = 'sequel'

Если вам нужно вместо этого найти все приквелы Matrix 2, вы знаете, что это просто список фильмов с related_movie_id 2 в качестве продолжения:

SELECT movie_id FROM movie_relations 
WHERE related_movie_id = 2 AND relation_type = 'sequel'

Допустим, вам нужны все фильмы, связанные с матрицей 2 (которая имеет неявный приквел и непосредственно указанный ответвление):

SELECT DISTINCT(movies.id), title FROM movies 
    LEFT JOIN movie_relations mr_direct ON mr_direct.related_movie_id = movies.id 
    LEFT JOIN movie_relations mr_implicit ON mr_implicit.movie_id = movies.id 
WHERE mr_direct.movie_id = 2 OR mr_implicit.related_movie_id = 2;

+----+---------------+
| id | title         |
+----+---------------+
|  1 | Matrix        |
|  3 | The Animatrix |
+----+---------------+

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

...