2012-12-14 9 views
12

मैं एक नुस्खा डेटाबेस तैयार कर रहा हूं जिसे बहुत लचीला होना चाहिए क्योंकि यह सीधे हमारे बैक-ऑफ-हाउस इन्वेंट्री सिस्टम के साथ संचार करने जा रहा है।एक नुस्खा डेटाबेस तैयार करना जिसमें सामग्री और उप-व्यंजनों को शामिल करने की आवश्यकता है

  • पकाने की विधि:: इस तालिका नुस्खा तारीख में शामिल होंगे: नाम, खाना बनाना करने के चरणों, आदि
  • सामग्री/इन्वेंटरी: यह हमारे वापस आ गया है यह वही है मैं टेबल के संबंध में अब तक किया है घर की सूची का, इसलिए इसमें प्रत्येक उत्पाद के बारे में जानकारी होगी जिसका उपयोग हमारे व्यंजनों में किया जाएगा।
  • पकाने की विधि लाइन आइटम: यह मुश्किल टेबल है, मैं यहां सामग्री के साथ-साथ नुस्खा के लिए आवश्यक मात्रा के लिए लिंक भी सक्षम होना चाहता हूं, लेकिन मुझे नुस्खा तालिका (जैसे इस तरह से व्यंजनों को सीधे शामिल करने में सक्षम होना चाहिए) मारिनारा सॉस के रूप में हम घर बनाते हैं), और यही कारण है कि मुझे इस तालिका को डिजाइन करने का सबसे अच्छा तरीका पता लगाने में परेशानी हो रही है।

असल में, नुस्खा लाइन आइटम तालिका या तो सामग्री तालिका या आधार नुस्खा तालिका जिस पर लाइन आइटम की जरूरत है से जोड़ने के लिए सक्षम होने की जरूरत है और मुझे पता है कि क्या है कि संभाल करने के लिए सबसे प्रभावी तरीका होगा चाहते हैं ।

अग्रिम में आपका बहुत बहुत धन्यवाद!

+4

मुझे नहीं पता कि यह प्रश्न क्यों बंद कर दिया गया है - और निश्चित रूप से "गैर-रचनात्मक" होने के लिए नहीं। सवाल स्पष्ट और सटीक है। फिर से खोलने के लिए मतदान। – eggyal

+2

@eggyal मैं सहमत हूं। यह एक पूरी तरह से वैध डेटाबेस मॉडलिंग सवाल है। फिर से खोलने के लिए मतदान। –

+1

@eggyal, ब्रैंको Dimitrijevic; मुझे भी एक उचित सवाल की तरह लगता है। –

उत्तर

0

आपको तीन टेबल की आवश्यकता होगी: recipes तालिका, ingredients तालिका, और एक recipe_ingredients तालिका जो एक नुस्खा के लिए सामग्री निर्दिष्ट करती है। आप इस तालिका में मात्राओं जैसे अतिरिक्त जानकारी भी स्टोर कर सकते हैं। तो उदाहरण के लिए, यदि आपके पास सब्जी के सूप के लिए नुस्खा है, तो आपके पास संबंधित मात्रा वाले सब्जियों के लिए कई प्रविष्टियां होंगी। फिर इन प्रविष्टियों को एक विदेशी कुंजी के माध्यम से प्रासंगिक नुस्खा और अवयवों से जोड़ा जाएगा।

संपादित करें: इसके सरलतम पर स्कीमा:

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; 
+0

तो, रेसिपी_विंग्स टेबल में, आपके पास दो नामुमकिन विदेशी कुंजी होंगी, एक सामग्री तालिका में से एक और नुस्खा तालिका में से एक होगी? फिर बस उस नुस्खा_ंग्रेडिएंट के लिए प्रासंगिक कौन सा पॉप्युलेट करें? – VinceL

+0

मेरे पास शून्य की विदेशी कुंजी नहीं होगी क्योंकि तालिका एक नुस्खा को प्रभावी ढंग से एक घटक सौंप देगी, इसलिए दोनों विदेशी कुंजी आबादी में आ जाएंगी। यदि आपके पास कोई घटक नहीं है, तो इसे नुस्खा को सौंपा नहीं जा सकता है। –

+0

उस स्कीमा का उपयोग करके, किसी अन्य नुस्खा में एक घटक के रूप में "* मारिनारा सॉस *" (स्वयं एक नुस्खा) का उपयोग कैसे करता है? – eggyal

2

Ingredients और Recipes दोनों संभव 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) 
); 

फिर 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) 
); 
टी के साथ

उनका दृष्टिकोण, मैं अनुशंसा करता हूं कि आप सख्त SQL मोड सक्षम करें (या अन्यथा अमान्य मान ENUM टाइप किए गए कॉलम में खाली स्ट्रिंग '' के साथ एक विशेष त्रुटि मान के रूप में स्वीकार किए जाएंगे): यह उपर्युक्त मॉडल की इच्छित संदर्भित अखंडता को तोड़ सकता है। एक वैकल्पिक (लेकिन थोड़ा और कठिन) दृष्टिकोण ट्रिगर्स का उपयोग कर मैन्युअल रूप से संदर्भित अखंडता को लागू करना होगा।

यदि केवल MySQL समर्थित CHECK बाधाओं, हुह?

+0

नमस्ते उदासीन, मैं आपके साथ ईमानदार होने जा रहा हूं, मैंने कभी भी इस प्रकार की विदेशी कुंजी का उपयोग नहीं किया है कि आप रेसिपी इटम्स टेबल पर वापस लिंक करने के लिए व्यंजनों और सामग्री तालिकाओं पर इसका उपयोग कर रहे हैं, विशेष रूप से यह पंक्ति: 'विदेशी कुंजी (IngredientID, टाइप) संदर्भ पकाने की विधि ITems (ItemID, प्रकार) 'मैं आमतौर पर उन्हें उसी तरीके से कार्यान्वित करता हूं जैसे कि आप इसे पकाने की विधि इटम्स टेबल पर कैसे सेट करते हैं। तो मेरा सवाल यह है कि, इस सेटअप का उपयोग कर अन्य व्यंजनों के लिए एक संघटक अभी भी पुन: प्रयोज्य होगा? आपकी प्रतिक्रिया के लिए बहुत बहुत धन्यवाद! – VinceL

+0

@ विंसल: सभी 'विदेशी कुंजी' उन लोगों को अनुमत रिकॉर्ड है जहां सूचीबद्ध स्थानीय कॉलम संदर्भित तालिका में मेल खाते हैं। इस मामले में, 'सामग्री' तालिका में रिकॉर्ड्स 'आईडी' * और * टाइप' दोनों पर 'पकाने की विधि' से मेल खाना चाहिए (लेकिन चूंकि 'सामग्री। टाइप' मूल्य 'संघटक' 'तक सीमित है, इस प्रकार यह सुनिश्चित करता है कि 'संघटक' 'पकाने की विधि 'नहीं हो सकता है; बातचीत' व्यंजनों 'तालिका के बारे में सच है)। चूंकि 'रेसिपीलाइन इटम्स.इटेम आईडी' संदर्भ 'पकाने की विधि इटम्स', लेकिन 'पकाने की विधि। टाइप' पर किसी भी बाधा के बिना, यह 'सामग्री' और 'व्यंजनों' दोनों का संदर्भ दे सकता है। – eggyal

+0

ठीक है, मुझे लगता है कि मुझे अब इसकी समझ है, और मुझे लगता है कि यह बहुत अच्छा समाधान है। मेरे पास एक और सवाल है, 'पकाने की विधि' तालिका और 'पकाने की विधि' टाइम्स दोनों पर मात्रा क्षेत्र रखने का क्या उद्देश्य है? मैं देख सकता हूं कि इसकी 'रेसिपीलाइन इटम्स' टेबल पर इसकी आवश्यकता क्यों है, लेकिन मुझे यकीन नहीं है कि इसका उपयोग 'पकाने की विधि' तालिका पर क्या होगा। आपकी स्पष्टीकरण के लिए फिर से धन्यवाद! – VinceL

0

एक तरीका।

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 

तो यदि कोई घटक एक पकवान है, तो इसमें एक नुस्खा है।

ओपी से एक प्रश्न के बाद संशोधित, जिसने मेरे संभावित उत्तर में एक कमजोर दोष की ओर इशारा किया।

+0

कोई कैसे पहचानता है कि 'मारिनारा सॉस' नामक घटक वास्तव में एक ही नाम के पकवान जैसा ही है? – eggyal

+0

डिशआईड = संघटक आईडी, उपरोक्त में, हम्म, पकड़ो। –

0

यह स्क्रिप्ट आपको एक डेटाबेस बनाएगी जो आपको व्यंजनों, अवयवों, व्यंजन संरचना (ingredients_recipes) और आपके लिए सूची और संरचना के लिए एकता का प्रबंधन करने देगी।यह आपको अपने इन्वेंट्री इतिहास को प्रबंधित करने देता है।

क्वेरी अपने वर्तमान नुस्खा प्राप्त करने के लिए है, सामग्री की जरूरत है, मात्रा की जरूरत है और शेयर इस समय मौजूद है:

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); 

डेटाबेस:

-- -------------------------------------------------------- 
-- 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 @[email protected]@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 [email protected]_CHARACTER_SET_CLIENT */; 
+0

देरी के जवाब में मैं क्षमा चाहता हूं, आप एकता तालिका पर नाम फ़ील्ड का उपयोग कैसे करेंगे? सबसे पहले मैं सोच रहा था कि आप इसका उपयोग यह कहने के लिए करेंगे कि आप किस प्रकार का क्षेत्र एकजुट कर रहे थे (चाहे वह नुस्खा, नुस्खा_शोधक, या एक घटक हो), लेकिन फिर मैंने देखा कि यह अद्वितीय था। आपकी प्रतिक्रिया के लिए धन्यवाद, यह निश्चित रूप से दिलचस्प लग रहा है! – VinceL

+0

नाम केवल एकता का नाम है उदाहरण के लिए एल के लिए एल, मिलीलीटर के लिए एमएल, ग्राम के लिए जी और इसी तरह, वास्तव में यह "नाम" फ़ील्ड आपकी "ड्रॉपडाउन सूची" के लिए प्रदर्शन क्षेत्र है। यह अनोखा होना चाहिए, कल्पना करें कि आप व्यंजनों में उपयोग की जाने वाली एकता की तुलना करना चाहते हैं और जिस व्यक्ति का आप उपयोग करते हैं, वह प्रत्येक एकता के संदर्भ को अनूठा होना चाहिए। बस समानांतर बनाने के लिए, इस प्रकार के क्षेत्र के लिए अद्वितीय नहीं होने के कारण आपको ड्रॉपडाउन सूची में 3 गुना "किलोग्राम" के साथ फ्रंटएंड ऐप के लिए छोड़ दिया जाएगा ... आप कौन सी चुनेंगे? अद्वितीय बाधा आपको इस तरह के डेटा को डुप्लिकेट नहीं करने देगी। – guignol

7

जैसे आप एक की जरूरत है लगता है डेटाबेस मॉडल इस के समान:

enter image description here

इस मॉडल में निम्नलिखित गुण हैं:

  • अनिवार्य रूप से, प्रत्येक नुस्खा चरणों की एक श्रृंखला है।
  • हर कदम एक ही नुस्खा के अन्य कदम (STEP_NO), एक इकाई (बड़े पैमाने पर, मात्रा, गिनती ...), कि इकाई आदि
  • में एक मात्रा एक विशेष कदम या तो से जुड़ा है करने के लिए अपने आदेश रिश्तेदार एक घटक (जब INGREDIENT_ID गैर-न्यूल होता है) या किसी अन्य नुस्खा (जब SUBRECIPE_ID गैर-नल होता है)।
  • इसके अलावा, एसटीईपी एक काफी मानक जंक्शन तालिका है जो कई से अधिक रिश्तों को लागू करती है, जिसका अर्थ है कि एक ही घटक का उपयोग कई व्यंजनों (या एक ही नुस्खा के कई चरणों) में भी किया जा सकता है। नुस्खा कई अन्य व्यंजनों का "उप-नुस्खा" हो सकता है।
  • यह अनिवार्य रूप से एक निर्देशित ग्राफ है। डेटा मॉडल स्वयं चक्रों को नहीं रोकेगा - उन्हें क्लाइंट कोड स्तर से बचा जाना चाहिए और संभावित रूप से ट्रिगर्स द्वारा पता लगाया जाना चाहिए।

MySQL समर्थित जांच की कमी (जो यह doesn't), आप यह सुनिश्चित कर सकते हैं कि एक (लेकिन दोनों नहीं) उनमें से तो है में गैर-शून्य इस तरह:

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

जैसा कि यह खड़ा है, आपको इसके लिए एक ट्रिगर की आवश्यकता होगी।

+0

अच्छा जोड़ें! धन्यवाद – guignol

संबंधित मुद्दे