Я думаю, что сбивает с толку то, что с рецептом нужно подумать о двух разных вещах: «Предметы» и «Шаги».
Одна структура базы данных, которая приходит на ум, это Структура звездной схемы , которая аккуратно разделяет эти идеи (на Dimension
и Fact
таблицы соответственно).
Краткое описание каждого:
Размер
- «Состояние чего-то», т. Е. Запись просто для описания того, что это за вещь. Таблица адресов клиента будет примером таблицы измерений.
Факт
- «Вещи, изменяющиеся со временем», то есть каждая запись относится к таблице измерений, но имеет изменяющиеся значения. Примером могут быть отправленные покупки с веб-сайта по адресу клиента. Адрес остается прежним, но посылки постоянно добавляются в таблицу.
Нельзя сказать, что таблицы измерений тоже не меняются; очевидно, что новые пользователи регистрируются на сайтах постоянно. В приведенном выше примере адреса, если клиент должен изменить свой адрес, новое значение primary key
будет добавлено для нового адреса.
Теперь перейдем к примерам ваших рецептов:
Представь, что ты что-то готовишь. Я бы положил все, что вы держите в руках, в таблицу «измерений». Например: DIM_INGREDIENT
(с такими столбцами, как INDREDIENT_ID
, INGREDIENT_NAME
) и DIM_AMOUNT
(AMOUNT_ID
, AMOUNT
, UNITS
) для описания сумм. И DIM_ACTION
(ACTION_ID
, TYPE
, LENGTH
, UNITS
) для описания действия. Есть еще кое-что, что вы можете придумать; Вот несколько, чтобы начать.
Любые шаги, которые я предприму, могут быть в таблице FACT_RECIPE_STEPS
, которая будет отображаться во все таблицы измерений. Любой шаг, который не имеет логического шага, будет иметь значение null
(т.е. перемешивание в течение 5 минут будет иметь значение NULL для INGREDIENT_ID
).
FACT_RECIPE_STEPS
может выглядеть так:
RECIPE_ID
, RECIPE_STEP
, ACTION_STEP_ID
, INGREDIENT_ID
, AMOUNT_ID
, ACTION_ID
Что сбивает с толку, так это «шаг» взбивания всего вместе. Я поместил это в другую таблицу FACT
, называемую FCT_ACTION_STEP
, поскольку "взбивание" - это одно действие в списке рецептов, но для выполнения действия вам действительно нужно сделать три вещи.
Я думаю, что следующие таблицы будут выглядеть с вашими данными:
DIM_INGREDIENT
INGREDIENT_ID: 1
INGREDIENT_NAME: 'Scrambled eggs'
INGREDIENT_ID: 2
INGREDIENT_NAME: 'Salt'
INGREDIENT_ID: 3
INGREDIENT_NAME: 'Pepper'
INGREDIENT_ID: 4
INGREDIENT_NAME: 'Eggs'
INGREDIENT_ID: 5
INGREDIENT_NAME: 'Butter'
DIM_ACTION
ACTION_ID: 1
TYPE: 'Cook'
LENGTH: 5
UNITS: 'minutes'
ACTION_ID: 2
TYPE: 'Whisk'
LENGTH: null
UNITS: null
FCT_ACTION_STEP
STEP_ID: 1
ACTION_ID: 2
DIM_AMOUNT
AMOUNT_ID: 1
AMOUNT: 1
UNITS: 'grams'
AMOUNT_ID: 2
AMOUNT: 2
UNITS: null
FACT_RECIPE_STEPS
RECIPE_ID, RECIPE_STEP, ACTION_STEP_ID, INGREDIENT_ID, AMOUNT_ID, ACTION_ID
EDIT:
Я был немного неуверен в том, как сделать часть рецепта "Взбитые", и подумал, что, когда вы добавляете взбитую смесь в конечный результат, это все равно, что добавить в рецепт один ингредиент. Тем не менее, вам нужно приготовить смесь раньше, и она состоит из трех этапов. По сути, это как собственный маленький рецепт, и FACT_ACTION_STEP
учитывает этот другой «рецепт», чтобы иметь возможность добавить результат на одну строку в таблицу FACT_RECIPE_STEPS
.
Теперь, когда я думаю об этом немного больше, может быть, лучше просто назначить «Whisked» в качестве собственного рецепта в FACT_RECIPE_STEPS
и DIM_INGREDIENT
(что-то вроде «Взбитые специи для яиц») + и избавиться от него. таблицы FACT_ACTION_STEP
в целом. Таким образом, вы можете легко сделать более сложные рецепты, такие как «Яйца и блинный завтрак», где часть «Яйца» является результатом этого рецепта.