Stephan Wahlen
Stephan Wahlen

Reputation: 23

Multiple row conditions in WHERE clause

I am having trouble writing the following query in MySQL. I have a table called pizz0r_pizza_ingredients which looks something like this:

| id | pizza_id | ingredient | amount | measure |
+----+----------+------------+--------+---------+
| 6  |    1     |    15      |   3    |    4    |
|178 |    17    |    1       |   160  |    1    |
| 3  |    1     |    20      |   3    |    4    |

I want to search for pizzas where the ingredients have specific requirements such as the following:

SELECT `pizza_id` 
FROM `pizz0r_pizza_ingredients` 
WHERE `ingredient` = 15 AND `ingredient` != 20 
GROUP BY `pizza_id`

I am trying to get entries where ingredient is equal to 15, but ignores that pizza_id if it also has ingredient 20.

The current result is 1, but in this example nothing should be returned.

Upvotes: 2

Views: 102

Answers (5)

Gordon Linoff
Gordon Linoff

Reputation: 1269803

I like to handle these problems using group by and having:

SELECT `pizza_id` 
FROM `pizz0r_pizza_ingredients` 
GROUP BY `pizza_id`
HAVING SUM(ingredient = 15) > 0 AND
       SUM(ingredient = 20) = 0;

You can add as many new requirements as you like. The SUM() expression counts the number of ingredients of a certain type. The > 0 means that there is at least one on the pizza. The = 0 means that there are none.

Upvotes: 2

AdamMc331
AdamMc331

Reputation: 16690

One option you have is to use subqueries for this. To understand this best, I would first separate the two queries and then combine them.

The first one will pull all pizza_id that have ingredient 15:

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 15;

Then, you can write another one that searches for pizza_id where ingredient is equal to 20:

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 20;

Last, you can combine the two by using the NOT IN clause. In other words, you can select all pizza_id that meet the first condition, where the id is NOT IN the pizza_ids that meet the second condition:

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 15 AND pizza_id NOT IN(
  SELECT DISTINCT pizza_id
  FROM myTable
  WHERE ingredient = 20);

EDIT

Here is an SQL Fiddle.

EDIT 2

This is a subject known as relational division. There is another example similar to this here.

Upvotes: 0

SouravA
SouravA

Reputation: 5243

EDIT: Your question was unclear earlier. If you wanted to exclude pizzas with ingredient 20, you can use the below:

select pizzaid from pizz0r_pizza_ingredients where ingredient = 15
EXCEPT
select pizzaid from pizz0r_pizza_ingredients where ingredient != 20

NOTE: EXCEPT is generally faster than join or not in

Upvotes: 0

Saharsh Shah
Saharsh Shah

Reputation: 29051

Try this:

SELECT P1.pizza_id 
FROM pizz0r_pizza_ingredients P1 
LEFT OUTER JOIN pizz0r_pizza_ingredients P2 ON P1.pizza_id = P2.pizza_id AND P2.ingredient IN (20, 21)
WHERE P1.ingredient = 15 AND P2.id IS NULL
GROUP bY P1.pizza_id;

Upvotes: 2

Rowland Shaw
Rowland Shaw

Reputation: 38130

You need to combine the two sets of data - everything you might want, and then exclude those that intersect your unwanted ingredients, so something like:

SELECT DISTINCT
            wanted.pizza_id

FROM        pizz0r_pizza_ingredients wanted 

LEFT JOIN   pizz0r_pizza_ingredients dontwant
    ON      wanted.pizza_id = dontwant.pizza_id
    AND     dontwant.ingredient IN ( 20, 21 )

WHERE       wanted.ingredient IN ( 15 ) -- You could have multiples, if you wanted ham OR chicken, for example
    AND     dontwant.pizza_id IS NULL -- No bad ingredients

Upvotes: 0

Related Questions