简体   繁体   中英

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.

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;

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.

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

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

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM