MySQL选择IN(包含)和NOT IN(排除)

时间:2014-04-09 21:43:57

标签: mysql sql

我有一个食谱表,食谱编号和成分列表。我想选择具有(成分列表)和(没有其他成分列表)的食谱编号。 提前感谢任何方向。

CREATE TABLE recipe (
    id INT PRIMARY KEY,
    recipe_num INT,
    ingredient VARCHAR(20)
);

INSERT INTO recipe VALUES (1,1,'salt'),(2,1,'pork'),(3,1,'pepper'),(4,1,'milk'),(5,1,'garlic'),
(6,2,'steak'), (7,2,'pepper'),(8,2,'ketchup'),
(9,3,'fish'),(10,3,'lemon'),(11,3,'cheese'),
(12,4,'veal'),(13,4,'cream'),(14,4,'salt'),(15,4,'garlic');


select * from recipe;
+----+------------+------------+
| id | recipe_num | ingredient |
+----+------------+------------+
|  1 |          1 | salt       |
|  2 |          1 | pork       |
|  3 |          1 | pepper     |
|  4 |          1 | milk       |
|  5 |          1 | garlic     |
|  6 |          2 | steak      |
|  7 |          2 | pepper     |
|  8 |          2 | ketchup    |
|  9 |          3 | fish       |
| 10 |          3 | lemon      |
| 11 |          3 | cheese     |
| 12 |          4 | veal       |
| 13 |          4 | cream      |
| 14 |          4 | salt       |
| 15 |          4 | garlic     |
+----+------------+------------+
15 rows in set (0.00 sec)

我可以选择包含肉类和奶制品的所有recipe_num。如何查询包含肉类而非乳制品的所有recipe_num?这似乎很容易,

SELECT 
    meat.recipe_num, meat.ingredient as meat, dairy.recipe_num, dairy.ingredient as dairy
FROM
    recipe as meat, recipe as dairy
WHERE
    meat.ingredient IN ('pork' , 'steak','chicken','veal')
    AND dairy.ingredient IN ('milk' , 'cheese')
    AND meat.recipe_num = dairy.recipe_num;

+------------+------+------------+-------+
| recipe_num | meat | recipe_num | dairy |
+------------+------+------------+-------+
|          1 | pork |          1 | milk  |
+------------+------+------------+-------+

1行(0.00秒)

3 个答案:

答案 0 :(得分:0)

使用LEFT JOIN匹配两个子表,然后在乳品列中测试NULL,找到不匹配的食谱。

SELECT DISTINCT meat.recipe_num
FROM recipe AS meat
LEFT JOIN recipe AS dairy 
ON meat.recipe_num = dairy.recipe_num AND dairy.ingredient IN ('milk', 'cheese')
WHERE meat.ingredient IN ('pork' , 'steak','chicken','veal')
AND dairy.recipe_num IS NULL

或者,您可以使用更直观的NOT IN查询。但是,这可能效果不佳。

SELECT DISTINCT recipe_num
FROM recipe
WHERE ingredient IN ('pork' , 'steak','chicken','veal')
AND recipe_num NOT IN (SELECT recipe_num
                       FROM recipe
                       WHERE ingredient IN ('milk', 'cheese'))

答案 1 :(得分:0)

虽然可能徒劳无益,但这个问题的最后一部分仍留给读者练习......

SELECT * 
  FROM recipe a 
  JOIN recipe b 
    ON b.recipe_num = a.recipe_num 
  LEFT 
  JOIN recipe c 
    ON c.recipe_num = a.recipe_num 
   AND c.ingredient IN ('milk','cream') 
 WHERE a.ingredient IN ('pork','steak','veal');

答案 2 :(得分:0)

如果您只想要符合条件的recipe_num列表,则根本不需要JOIN,您只需使用HAVING条款:

SELECT recipe_num
FROM recipe
GROUP BY recipe_num
HAVING MAX(CASE WHEN ingredient IN ('pork' , 'steak','chicken','veal') THEN 1 END) = 1
   AND MAX(CASE WHEN ingredient IN ('milk' , 'cheese') THEN 1 ELSE 0 END) = 0

同样,您可以使用NOT EXISTS完成相同的操作:

SELECT DISTINCT recipe_num
FROM recipe a
WHERE a.ingredient IN ('pork','steak','chicken','veal')
  AND NOT EXISTS (SELECT recipe_num
                  FROM recipe b
                  WHERE b.ingredient IN ('milk','cream')
                    AND a.recipe_num = b.recipe_num)