473,395 Members | 1,706 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Query to get list of cocktails given ingredients

Hi, I'm trying to write a query to get a list of drink recipes which have one or more of the selected ingredients....

so, in a search form I want to be able to choose 1 or more ingredients and have sql return all drinks with that combination of ingredients.

I have 3 tables (only relevant fields shown here):

tDrinks
-drinkid
-drinkname
-drinkdesc

tIngredients (not needed in the query but used elsewhere)
-ingredientid
-ingredientname

tDrinkIngredients
-drinkid
-ingredientid
-qty

so, I can get a list of drinks given one ingredient:
Expand|Select|Wrap|Line Numbers
  1. SELECT tDrinks.drinkid,tDrinks.drinkname FROM tDrinks left join tDrinkIngredients on tDrinks.drinkid=tDrinkIngredients.drinkid where tDrinkIngredients.ingredientid=5 
but I am having difficulty understanding how to involve more than one ingredient. Any ideas / suggestions would be much appreciated....
Sep 15 '08 #1
12 3706
Atli
5,058 Expert 4TB
Do you wan't to get a list of drinks that match all the given ingredients or just one of them?

If it's the first one, you could try using a INNER JOIN, and specify all the ingredients you want in the ON clause.
It's only a small modification to the query you posted. (I reformatted it a bit to):
Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname 
  2. FROM tDrinks AS d
  3. INNER JOIN tDrinkIngredients AS i
  4.   ON d.drinkid = i.drinkid
  5.   AND i.ingredientid = 1
  6.   AND i.ingredientid = 2
  7.   AND i.ingredientid = 3
  8.   /* etc */
  9.  
If it's the second option, you could use the IN() function.
Like:
Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname 
  2. FROM tDrinks AS d
  3. INNER JOIN tDrinkIngredients AS i
  4.   ON d.drinkid = i.drinkid
  5.   AND i.ingredientid IN(1, 2, 3)
  6.  
EDIT: On second though, the first query is obviously not going to work, seeing as I'm checking the same field for several values. See post #7.
Sep 15 '08 #2
Hi, thanks for the quick response...yes, I want to get drinks only if they have ALL the ingredients searched for....

the second example you gave works great for getting any one ingredient, but I can't seem to get the first query working......here is some more information on the structure of the tables so hopefully someone can help me:



So as you can see in the image, I need to pull any drinks with a combination of any 1 or more ingredient.

Much appreciate any replies...thanks!
Sep 15 '08 #3
Atli
5,058 Expert 4TB
What's the problem with the first query?
How is it not working?
Sep 16 '08 #4
HI, using the following query:


Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i 
  4. ON d.drinkid = i.drinkid 
  5. AND i.ingredientid =63 
  6. AND i.ingredientid =211
  7.  
it returns an empty recordset, when it should return a few records.
Sep 16 '08 #5
Hi, I thought this was it but it doesn't work correctly either...it's jsut a different way of doing it:

Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname 
  2. FROM tDrinks AS d 
  3. INNER JOIN (SELECT i.drinkid
  4. FROM tDrinkIngredients AS i
  5. WHERE i.ingredientid IN (63,211))
  6.  AS i
  7. ON d.drinkid = i.drinkid
  8.  
Sep 16 '08 #6
Atli
5,058 Expert 4TB
HI, using the following query:


Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i 
  4. ON d.drinkid = i.drinkid 
  5. AND i.ingredientid =63 
  6. AND i.ingredientid =211
  7.  
it returns an empty recordset, when it should return a few records.
Ahh ok. I see the problem. That query is checking whether the same "i.ingredientid" field has two different values, which is obviously not going to happen.

To make that query work, you would have to JOIN the ingredient table for every ingredient you want checked. Like:
Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i1 
  4.   ON d.drinkid = i1.drinkid 
  5.   AND i1.ingredientid=63 
  6. INNER JOIN tDrinkIngredients AS i2 
  7.   ON d.drinkid = 2i.drinkid 
  8.   AND i2.ingredientid=211
  9.  
It doesn't look pretty, but it's only using integers, who are all presumably keys, so the extra JOINS shouldn't cause much performance loss.
Sep 16 '08 #7
coolsti
310 100+
HI, using the following query:


Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i 
  4. ON d.drinkid = i.drinkid 
  5. AND i.ingredientid =63 
  6. AND i.ingredientid =211
  7.  
it returns an empty recordset, when it should return a few records.
Why would not this work?

Expand|Select|Wrap|Line Numbers
  1. SELECT d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i 
  4. ON d.drinkid = i.drinkid 
  5. AND i.ingredientid IN (63,211)
  6.  
It is basically your second attempt, but I do not have the WHERE i.ingredientid IN ( ... list ...) within a subquery.
Sep 16 '08 #8
Atli
5,058 Expert 4TB
Why would not this work?
He want's a list of drinks that use all the specified ingredients.
That would return all drinks that use any of them.
Sep 16 '08 #9
coolsti
310 100+
Ah I see the problem now!

I don't know if Atli's suggestion works, but I did something like this a while back in another context.

Expand|Select|Wrap|Line Numbers
  1. SELECT count(*) as rowcount, d.drinkid, d.drinkname  
  2. FROM tDrinks AS d  
  3. INNER JOIN tDrinkIngredients AS i 
  4. ON d.drinkid = i.drinkid 
  5. AND i.ingredientid IN (63,211)
  6. GROUP BY d.drinkid HAVING rowcount = 2
  7.  
The above might work (haven't tested it for syntax errors and logic errors).

The idea is this: Since your one to many relationship in the join (a drink has many ingredients) will give you multiple rows for the same drinkid if there are more than one ingredient match, you need to do a GROUP BY.

Then you just add this count(*) as rowcount attribute to your query. With the Group by clause, it will give you the count of how many rows have been grouped for each drink.

If only one ingredient matched, rowcount for that drink is 1. If two ingredients matched, then rowcount will be 2.

In your situation, you want all the drinks that match ALL the ingredients that you have selected. So you want only the rows in your results that have rowcount equal to the number of drinks. Hence, you use the HAVING rowcount = 2 here.

To make this flexible for all user selections, you of course need to substitute the IN clause with the list of ingredients that were actually selected, and you need to substitute the value of 2 in the "HAVING rowcount = 2" with the number of ingredients that were selected.

Or did I misunderstand the problem yet once again? :)
Sep 16 '08 #10
coolsti
310 100+
Oops, I just reread my answer and I made a mistake in the explanation:

In your situation, you want all the drinks that match ALL the ingredients that you have selected. So you want only the rows in your results that have rowcount equal to the number of selected ingredients. Hence, you use the HAVING rowcount = 2 here.

Substitute ingredients for drinks!
Sep 16 '08 #11
Hi, thanks to both Alti and Coolsti. I can use both of those queries in my application. Coolsti, that idea of using rowcounts is a good one as I can do partial ingredient matches on a drink...ie these 6 drinks have 5/5 of the ingredients...these next 20 have 4/5 etc......gives a good way of showing related drinks as well as exact matches.

Thanks!
Sep 17 '08 #12
coolsti
310 100+
Hi, thanks to both Alti and Coolsti. I can use both of those queries in my application. Coolsti, that idea of using rowcounts is a good one as I can do partial ingredient matches on a drink...ie these 6 drinks have 5/5 of the ingredients...these next 20 have 4/5 etc......gives a good way of showing related drinks as well as exact matches.

Thanks!
You are most welcome! I am just giving back what was given to me. I had a similar situation: I allowed a user to select various inspection results criteria from a large list, and wanted to select from the database for view only those items for which there was a match with all of the selected criteria, be it only one or two or five, etc.

I had no idea how to do it, and I posted a question on another forum long ago, and someone was nice enough to point out the trick with the HAVING clause to me.

And yes, it is versatile, because you can have the criterion after the HAVING be an equality or a range.
Sep 17 '08 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

5
by: Muhd | last post by:
To start off i have a database table that consists of "profiles", another that consists of "users" and finally one that consists of "exclusions", these are defined in the DDL below. I am trying to...
33
by: Jim Cobban | last post by:
I cannot get Netscape 4.79 to properly display the ordered list in the following fragment. <P>Get a specific portion of the date. Depending upon the value of index: <ol start=0> <li>complete...
2
by: ormy28 | last post by:
I really need some help with the following problem if anyone would be willing. I need a list box to list the opposite of what appears in a query. Heres the details: My database is for a...
0
by: Paul | last post by:
Hello everybody, I am writing a small recipe database. In order to create a correct ingredients list (the largest ingredient placed first and the ingredients summed up (sorted) where needed), I...
2
by: shanfitzpatrick | last post by:
Ach, I'm in a bind...i can't get one of my queries to work properly. And i'm certain it's because I don't know how to write the expression correctly... I am creating a database that enters items...
4
by: KiwiGenie | last post by:
Hi..I’ve been teaching myself access through trial and error and google, but now I am completely confused and STUCK! These are the relevant forms in my database: frm_Recipes: Main form for...
4
by: kdubble | last post by:
Hi I am trying to get the results of a query to show only unique student records (not duplicates). Is there a simple way to make the criteria field do this? I am not too familiar with SQL. ...
4
by: =?Utf-8?B?amF5dg==?= | last post by:
The best way to explain it, is to show you what i "thought" should work and hope that you can show me a way to make it work please and thanks... string ingredients = "pepper,salt,eggs"; strSql...
4
by: zion4ever | last post by:
Hello good people, Please bear with me as this is my first post and I am relative new to ASP. I do have VB6 experience. I have a form which enables users within our company to do an intranet...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.