2011-02-06 2 views
0

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

Первоначально я делал это:

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

Так Матрица 2 является продолжением матрицы, но потом я понял, что это, кажется, не имеет смысла хранить отношение соответствующего фильма вместо соотношения фактического фильма. Затем я попытался это вместо:

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

Теперь я храню фактическое отношение фильма вместо соответствующего фильма, так что строка имеет смысл. Кроме того, более буквальное, Матрица приквел Матрица 2.

Однако потом я понял, в передней части с помощью 2-го, как он будет выглядеть, как это на странице Матрица: приквел - Матрица 2

И для матрицы 2 страницы: Продолжение - Матрица

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

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

ответ

0

Вам не нужно сохранять как обратные, так и форвардные отношения. В отличие от связанного списка, вам не нужно хранить указатели 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 | 
+----+----------+---------------+------------------+ 

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

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

Если вам нужно вместо этого найти все сиквелы из Матрицы 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 | 
+----+---------------+ 

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

+0

Хм, но для этого так сложно получить название собственно связанного фильма, а не самого фильма. То есть если я хочу узнать названия связанных фильмов для Matrix, я бы использовал: SELECT title FROM movies m INNER JOIN movies_relations mr ON m.id = mr.movie_id WHERE m.id = 1' Но это даст мне название «Матрица», которая является собственно фильмом, а не названием связанного фильма. Возможно, у меня есть неправильный запрос? Выполняя это так, вам также нужно перевернуть выделение и поля туда и обратно. С оригинальными способами, которыми я пользовался, я могу придерживаться одного запроса для всего. – Joker

+0

Запрос обратный: 'SELECT movies.title FROM movies LEFT JOIN movie_relations ON movie_relations.related_movie_id = movies.id WHERE movie_relations.movie_id = 1;' будет вытягивать правильные связанные фильмы. Я обновляю свой ответ, чтобы показать, как он работает с несколькими отношениями, и делать это в одном запросе. – ash

+0

Обновлено, см. Ответ. – ash