Как правильно спроектировать БД?

Здравствуйте,
И так, есть две таблицы: Блюда и ингредиенты. Требуется связать их, но количество ингредиентов в каждом блюде не фиксированое. В блюде может быть и 2 ингредиента, и 10, или даже 20. В чем вопрос то?
Как правильно связать ингредиенты с блюдом? Была идея просто создать промежуточную таблицу, в которой хранился бы ID блюда и ингредиента. Но мне эта идея не очень нравится, неужели нельзя сделать это по-другому? Нужен совет, спасибо заранее. Использую встроеную MySql базу.

Ингредиенты могут повторятся в разных блюдах
  • Вопрос задан
  • 5102 просмотра
Решения вопроса 1
metamorph
@metamorph
Зависит от того, что именно Вы делаете.

Если это, грубо говоря, лабораторная работа по нормализации таблиц - тогда ТОЛЬКО через промежуточную таблицу, за иные варианты Вам снимут голову.

Many-to-many через pivot table чаще всего не нравится тем, что для добычи результата приходится делать двойной джойн, а потом каким-то образом разгребать дублирующиеся данные "основной" таблицы.

Если не требуется искать блюда по ингредиентам ("найти все блюда, в которых есть чеснок") - тогда можно и схитрить немного.

Обычный вариант обхода - добавить немного скриптовой части:
- выгребаем данные основной таблицы: select * from meals where ...;
- скриптом собираем полученные ID в массив и выполняем второй запрос: select * from ingredients inner join meals_ingredients where meals_ingredients.meal_id IN (...тут список полученных на первом шаге id)
- разгребаем полученные данные по конкретным meal_id.

Немного более извращенный - сериализовать список использованных ингредиентов в отдельное поле блюда (например, тип text). При этом в базах, отличных от mysql, можно будет еще и отлично искать по этому полю. Этакий noSQL в условиях, максимально приближенных к боевым.

Фишка в том, что классическая нормализация many-to-many заранее учитывает тот факт, что первичные ключи могут (внезапно!) меняться. На практике же это ооооочень редкий случай.

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

Так что, как говорится, не Коддом единым.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
akashtrih
@akashtrih
Идея с промежуточной таблицей хорошая, способов лучше не вижу. Если вам не нравится то, что придётся возиться с промежуточной таблицей, можно чуть-чуть упростить себе задачу, используя внешние ключи. То есть, например, сделать так, чтобы при удалении блюда, автоматически удалялись и соответствующие записи из промежуточной таблицы.
Ответ написан
Комментировать
Liny_li
@Liny_li
Промежуточная таблица для связи «многие к многим» — действительно оптимальный вариант. Чем он вам не нравится?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы