2012-08-16 8 views
8

मेरे पास एक SQL क्वेरी है जो मुझे स्टंप कर चुकी है। असल में, मेरे पास Recipes तालिका है जिसमें कई व्यंजन हैं (जैसा कि आपको कोई संदेह नहीं है)। मेरे पास Ingredients तालिका है जिसमें सभी प्रकार के अवयव शामिल हैं। मेरे पास RecipeIngredients तालिका है जो एक नुस्खा को जोड़ती है जो इसका उपयोग करती है।आप केवल दूध, अंडे, मक्खन, आटा, चीनी, और नमक के साथ कितने व्यंजन बना सकते हैं?

CREATE Table Recipes 
(
    RecipeId int4, 
    Title varchar(100) 
); 

CREATE Table Ingredients 
(
    IngredientId int4, 
    Name varchar(100) 
); 

CREATE Table RecipeIngredients 
(
    RecipeId int4, 
    IngredientId int4, 
    Amount int2 
); 

CREATE Table PopularIngredients 
(
    IngredientId int4 
); 

मेरा लक्ष्य सभी व्यंजनों का उपयोग की एक सूची प्राप्त करने के लिए है: अंत में, मैं एक PopularIngredients तालिका (? यह वास्तव में एक दृश्य है, लेकिन कौन परवाह करता है) कि सबसे लोकप्रिय तत्व शामिल लोगों को अपने रसोई घर में हो सकता है है केवल लोकप्रिय सामग्री।

नमूना डेटा के साथ एक एसक्यूएल फिडल here पाया जा सकता है।

क्या मैं के लिए देख रहा हूँ एक प्रश्न है कि चिकन सलाद और Pancakes वापस आ जाएगी है। एलीगेटर बर्गर वापस नहीं किया जाएगा, क्योंकि यह एलीगेटर का उपयोग करता है जो एक लोकप्रिय घटक नहीं है।

मैंने उप-चयन और ALL कीवर्ड से जुड़े कुछ चीजों की कोशिश की है, लेकिन कोई भाग्य नहीं है। मैंने विभिन्न आंतरिक और बाहरी जुड़ने की कोशिश की है, लेकिन पकाने की विधि तब भी दिखाई देगी जब तक कि इसकी कम से कम एक सामग्री लोकप्रिय न हो। कोई भी सहायताकाफी प्रशंसनीय होगी!

मैं पोस्टग्रेज़ 9.1 का उपयोग कर रहा हूं।

+1

इस एक मॉडल सवाल है; मैं इसे नए पोस्टर दिखाने के लिए इसका उपयोग कर रहा हूं कि इसे सही तरीके से कैसे किया जाए। –

उत्तर

7

यह उन सभी व्यंजनों को प्राप्त करता है जिनमें लोकप्रिय सामग्री तालिका में कोई सामग्री नहीं है।

select * from Recipes r where not exists (
    select * from RecipeIngredients ri 
    left join PopularIngredients pi on pi.IngredientId=ri.IngredientId 
    where ri.RecipeId=r.RecipeId and pi.IngredientId is null 
) 
+0

धन्यवाद! मुझे पता था कि इसमें कहीं भी 'अस्तित्व में नहीं' होगा, लेकिन मस्तिष्क इष्टतम स्थितियों पर काम नहीं कर रहा था .. –

5

WHERE NOT EXISTS प्रयुक्त इस्तेमाल किया PopularIngredients से याद कर रहे हैं सामग्री में से कोई भी सुनिश्चित करने के लिए देखने:

SELECT R.* 
FROM Recipes R 
WHERE NOT EXISTS (
    SELECT 1 
    FROM RecipeIngredients RI 
    LEFT JOIN PopularIngredients P ON P.IngredientId = RI.IngredientId 
    WHERE RI.RecipeId = R.RecipeId AND P.IngredientId IS NULL 
) 

Updated अपने SqlFiddle

2
select r.Title 
    from Recipes r 
    join RecipeIngredients ri 
    on r.RecipeId = ri.RecipeId 
    left outer join PopularIngredients pi 
    on ri.IngredientId = pi.IngredientId 
group by r.Title 
having count(case when pi.IngredientId is null then 1 end)=0 

या लगभग एक ही

select r.Title 
    from Recipes r 
    join RecipeIngredients ri 
    on r.RecipeId = ri.RecipeId 
    left outer join PopularIngredients pi 
    on ri.IngredientId = pi.IngredientId 
group by r.Title 
having count(pi.IngredientId)=count(ri.IngredientId) 
+1

मुझे यह दृष्टिकोण पसंद है क्योंकि यह अधिक सेट-आधारित है। हालांकि, हो रहा है कि क्लॉज "गिनती()" के बजाय "गिनती()" की बजाय "गिनती (अलग)" होनी चाहिए जहां एक घटक को एक से अधिक बार शामिल किया जा सकता है। –

+0

धन्यवाद! इस दृष्टिकोण के साथ '+ 1' भी पात्र है .. –

+0

@ गॉर्डन लिनॉफ - ??? मैं नहीं देखता कि DISTINCT जोड़ने से परिणाम में कोई फर्क पड़ सकता है, शायद इसे थोड़ा धीमा करने के अलावा। यदि नुस्खा में एक घटक दो बार प्रकट होता है तो बाहरी जुड़ाव या तो दो बार सफल होगा या दो बार विफल भी होगा। यह अभी भी DISTINCT के बिना सही परिणाम देता है। – dbenham

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