una sacar recetas receta hacer formato estandarizar estandar elementos ejemplos definicion datos costos como cocina mysql database-design

mysql - sacar - receta estandar definicion



DiseƱar una base de datos de recetas que debe incluir ingredientes y sub-recetas (5)

De una sola mano.

Dish Key ID Name 1 1 Snails in Marinara Sauce 2 2 Marinara Sauce 3 3 Glass of Water Ingredient Key DISHID Name 1 NULL Snail 2 NULL Tomato 3 NULL Onion 4 NULL Evian 5   2   Marinara Sauce Recipe DishID IngredientKey Qty UOM 1 1 6 Each 1 5 3 TblSpoon 2 2 2 Each 2 3 1 Each 3 4 275 Millilitres

Entonces, si un ingrediente es un plato, tiene una receta.

Enmendado después de una pregunta de OP, que apunta a un pequeño error en mi posible respuesta.

Estoy diseñando una base de datos de recetas que debe ser muy flexible, ya que se va a comunicar directamente con nuestro sistema de inventario de respaldo. Esto es lo que tengo hasta ahora con respecto a las tablas:

  • Receta: esta tabla contendrá la fecha de la receta: el nombre, los pasos necesarios para cocinar, etc.
  • Ingredientes / Inventario: este es nuestro inventario de la parte posterior de la casa, por lo que esta tendrá la información sobre cada producto que se utilizará en nuestras recetas.
  • Artículo de la línea de recetas: esta es la tabla engañosa, quiero poder vincular los ingredientes aquí, así como la cantidad necesaria para la receta, pero también necesito poder incluir directamente las recetas de la tabla de recetas (como la salsa marinara que fabricamos en casa), y es por eso que estoy teniendo problemas para encontrar la mejor manera de diseñar esta tabla.

Básicamente, la tabla de elementos de la línea de recetas debe poder enlazar con la tabla de ingredientes o la tabla de recetas, dependiendo de qué línea de pedido se necesita y quiero saber cuál sería la forma más efectiva de manejarlo.

¡Muchas gracias de antemano!


Este script le creará una base de datos que le permitirá administrar recetas, ingredientes, la composición recip (ingredients recetes) y también unidades para su inventario y la composición. También le permite administrar su historial de inventario.

Aquí está la consulta para obtener su receta actual, los ingredientes necesarios, la cantidad necesaria y el stock que tiene actualmente:

SELECT recipes.id, recipes.name AS recipeName, ingredients.name AS ingredientNeeded, CONCAT(ingredients_recipes.Qty,'' '',neededUnities.name) AS neededQuantity, CONCAT(inventories.qty,'' '',inventoryUnities.name) AS availableQuantity FROM recipes LEFT JOIN ingredients_recipes ON recipes.id=ingredients_recipes.recipe_id LEFT JOIN ingredients ON ingredients_recipes.ingredient_id = ingredients.id LEFT JOIN inventories ON ingredients.id=inventories.ingredient_id LEFT JOIN unities AS inventoryUnities ON inventories.unity_id=inventoryUnities.id LEFT JOIN unities AS neededUnities ON ingredients_recipes.unity_id=neededUnities.id WHERE inventories.`update` = (SELECT MAX(`update`) FROM inventories AS inv WHERE inv.ingredient_id = inventories.ingredient_id);

la base de datos :

-- -------------------------------------------------------- -- Host: 127.0.0.1 -- Server version: 5.5.16 - MySQL Community Server (GPL) -- Server OS: Win32 -- HeidiSQL version: 7.0.0.4053 -- Date/time: 2012-12-14 16:33:22 -- -------------------------------------------------------- /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET NAMES utf8 */; /*!40014 SET FOREIGN_KEY_CHECKS=0 */; -- Dumping database structure for database DROP DATABASE IF EXISTS `database`; CREATE DATABASE IF NOT EXISTS `database` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `database`; -- Dumping structure for table database.ingredients DROP TABLE IF EXISTS `ingredients`; CREATE TABLE IF NOT EXISTS `ingredients` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL, `unity_id` int(11) NOT NULL COMMENT ''for the default unity'', `Created` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `Unity_id` (`unity_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table database.ingredients: ~0 rows (approximately) DELETE FROM `ingredients`; /*!40000 ALTER TABLE `ingredients` DISABLE KEYS */; /*!40000 ALTER TABLE `ingredients` ENABLE KEYS */; -- Dumping structure for table database.ingredients_recipes DROP TABLE IF EXISTS `ingredients_recipes`; CREATE TABLE IF NOT EXISTS `ingredients_recipes` ( `id` int(10) NOT NULL AUTO_INCREMENT, `ingredient_id` int(10) NOT NULL, `recipe_id` int(10) NOT NULL, `Qty` float NOT NULL, `Unity_id` int(10) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ingredient_id_recipe_id` (`ingredient_id`,`recipe_id`), KEY `Unity_id` (`Unity_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table database.ingredients_recipes: ~0 rows (approximately) DELETE FROM `ingredients_recipes`; /*!40000 ALTER TABLE `ingredients_recipes` DISABLE KEYS */; /*!40000 ALTER TABLE `ingredients_recipes` ENABLE KEYS */; -- Dumping structure for table database.inventories DROP TABLE IF EXISTS `inventories`; CREATE TABLE IF NOT EXISTS `inventories` ( `id` int(10) NOT NULL AUTO_INCREMENT, `ingredient_id` int(10) NOT NULL COMMENT ''ingredient'', `qty` int(10) NOT NULL COMMENT ''quantity'', `unity_id` int(11) NOT NULL COMMENT ''unity for the ingredient'', `update` datetime NOT NULL COMMENT ''date of the inventory update'', UNIQUE KEY `id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table database.inventories: ~0 rows (approximately) DELETE FROM `inventories`; /*!40000 ALTER TABLE `inventories` DISABLE KEYS */; /*!40000 ALTER TABLE `inventories` ENABLE KEYS */; -- Dumping structure for table database.recipes DROP TABLE IF EXISTS `recipes`; CREATE TABLE IF NOT EXISTS `recipes` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL, `cooking` longtext NOT NULL, PRIMARY KEY (`id`), KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table database.recipes: ~0 rows (approximately) DELETE FROM `recipes`; /*!40000 ALTER TABLE `recipes` DISABLE KEYS */; /*!40000 ALTER TABLE `recipes` ENABLE KEYS */; -- Dumping structure for table database.unities DROP TABLE IF EXISTS `unities`; CREATE TABLE IF NOT EXISTS `unities` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- Dumping data for table database.unities: ~0 rows (approximately) DELETE FROM `unities`; /*!40000 ALTER TABLE `unities` DISABLE KEYS */; /*!40000 ALTER TABLE `unities` ENABLE KEYS */; /*!40014 SET FOREIGN_KEY_CHECKS=1 */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;


Necesitará tres tablas: una tabla de recipes , una tabla de ingredients y una tabla recipe_ingredients que asigna ingredientes a una receta. También puede almacenar información adicional en esta tabla, como cantidades. Entonces, por ejemplo, si tienes una receta para sopa de verduras, tendrías entradas múltiples para verduras con las cantidades correspondientes. Estas entradas se vincularán con la receta y los ingredientes pertinentes a través de una clave externa.

EDITAR: Esquema en su forma más simple:

CREATE TABLE `ingredients` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) TYPE=InnoDB; CREATE TABLE `recipes` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) TYPE=InnoDB; CREATE TABLE `recipe_ingredients` ( `recipe_id` int(10) unsigned NOT NULL, `ingredient_id` int(10) unsigned NOT NULL, `quantity` int(10) unsigned NOT NULL, KEY `recipe_id` (`recipe_id`), KEY `ingredient_id` (`ingredient_id`) ) TYPE=InnoDB; ALTER TABLE `recipe_ingredients` ADD CONSTRAINT `recipe_ingredients_ibfk_2` FOREIGN KEY (`ingredient_id`) REFERENCES `ingredients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT `recipe_ingredients_ibfk_1` FOREIGN KEY (`recipe_id`) REFERENCES `recipes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;


Ingredients y las Recipes son ambos posibles RecipeItems :

CREATE TABLE RecipeItems ( ItemID SERIAL, Type ENUM(''Ingredient'', ''Recipe''), Name VARCHAR(255) NOT NULL, Quantity FLOAT NOT NULL, INDEX (ItemID, Type) ); CREATE TABLE Ingredients ( IngredientID BIGINT UNSIGNED NOT NULL, Type ENUM(''Ingredient''), CostPrice DECIMAL(6,2), PRIMARY KEY (IngredientID), FOREIGN KEY (IngredientID, Type) REFERENCES RecipeItems (ItemID, Type) ); CREATE TABLE Recipes ( RecipeID BIGINT UNSIGNED NOT NULL, Type ENUM(''Recipe''), SellPrice DECIMAL(6,2), Date DATE, Instructions TEXT, PRIMARY KEY (RecipeID), FOREIGN KEY (RecipeID, Type) REFERENCES RecipeItems (ItemID, Type) );

Luego RecipeLineItems :

CREATE TABLE RecipeLineItems ( RecipeID BIGINT UNSIGNED NOT NULL, ItemID BIGINT UNSIGNED NOT NULL, Quantity FLOAT NOT NULL, PRIMARY KEY (RecipeID, ItemID), FOREIGN KEY (RecipeID) REFERENCES Recipes (RecipeID), FOREIGN KEY (ItemID) REFERENCES RecipeItems (ItemID) );

Con este enfoque, le recomiendo que habilite el modo SQL estricto (o los valores inválidos serán aceptados en las columnas con ENUM con la cadena vacía '''' como un valor de error especial): esto podría romper la integridad referencial deseada del modelo anterior. Un enfoque alternativo (pero un poco más tedioso) sería imponer la integridad referencial de forma manual utilizando activadores.

Si solo MySQL soportara restricciones CHECK , ¿eh?


Parece que necesita un modelo de base de datos similar a este:

Este modelo tiene las siguientes propiedades:

  • Básicamente, cada receta es una serie de pasos.
  • Cada paso tiene su orden relativo a otros pasos de la misma receta (STEP_NO), una unidad (masa, volumen, recuento ...), una cantidad en esa unidad, etc.
  • Un paso en particular está conectado a un ingrediente (cuando INGREDIENT_ID no es NULL) o a otra receta (cuando SUBRECIPE_ID no es NULL). 1
  • Aparte de eso, el STEP es una tabla de unión bastante estándar que implementa la relación muchos a muchos, lo que significa que el mismo ingrediente se puede usar en múltiples recetas (o incluso en varios pasos de la misma receta) y también una receta puede ser un "sub -recipe "de muchas otras recetas.
  • Esto es esencialmente un gráfico dirigido. El modelo de datos en sí no evitará los ciclos; deben evitarse en el nivel de código del cliente y posiblemente se detecten mediante desencadenantes.

1 Si MySQL admite restricciones CHECK (que no ), puede asegurarse de que uno (pero no ambos) de ellos no sea NULL como este:

CHECK ( (INGREDIENT_ID IS NULL AND SUBRECIPE_ID IS NOT NULL) OR (INGREDIENT_ID IS NOT NULL AND SUBRECIPE_ID IS NULL) )

Tal como está, necesitarás un disparador para eso.