MySQL:如果不是所有行值都为true,则排除子集

MySQL:如果不是所有行值都为true,则排除子集,mysql,Mysql,我有三个MySQL表:配料表、配方中的配料表和配方表,它们可以通过内部连接来获取配方中的配料。此外,配料表中有一列“素食者”。我想得到所有被认为是素食主义者的食谱,这意味着给定食谱的所有成分必须将素食主义者设置为1,这是一个BOOL/tinyint1 我研究过使用ALL的查询,没有MAX和其他各种东西,但我找不到有效的解决方案。最好的方法是什么?是否有比其他解决方案更有效的解决方案 仅附加相关表格信息: 我的查询的开始当前为: SELECT recipe.name, ingredient.nam

我有三个MySQL表:配料表、配方中的配料表和配方表,它们可以通过内部连接来获取配方中的配料。此外,配料表中有一列“素食者”。我想得到所有被认为是素食主义者的食谱,这意味着给定食谱的所有成分必须将素食主义者设置为1,这是一个BOOL/tinyint1

我研究过使用ALL的查询,没有MAX和其他各种东西,但我找不到有效的解决方案。最好的方法是什么?是否有比其他解决方案更有效的解决方案

仅附加相关表格信息:

我的查询的开始当前为:

SELECT recipe.name, ingredient.name
    FROM ingredients AS ingredient
    INNER JOIN ingredient_in_recipe AS ir
        ON ir.ingredient_id = ingredient.id
    INNER JOIN recipes AS recipe
        ON ir.recipe_id = recipe.id;

因此,我在结尾缺少WHERE、ALL、IN或something语句。

您可以尝试以下方法:

SELECT r.name FROM recipes r WHERE r.id NOT IN (
  SELECT ir.recipe_id FROM ingredient_in_recipe ir
  INNER JOIN ingredients i ON ir.ingredient_id = i.id
  WHERE i.vegeterian = 0
)

这样想吧

选择含有任何非素食成分的食谱。 从所有配方的集合中减去此集合。 这是一套含有非蔬菜成分的食谱

    select
      id 
    from
      recipes,
      ingredient_in_recipe,
      ingredients
    where
      ingredient_in_recipe.recipe_id = recipes.id
    and
      ingredient_in_recipe.ingredient_id = ingredients.id
    and
      ingredients.vegetarian <> 1
注意:为什么你要用锡纸来标记布林?使用Boolean标记Boolean

你的DB模型也很好。您的命名是一致和适当的

既然我们有了非素食主义的食谱,我们就从集合论的角度进行减法

select
  *
from
  recipes
where
  id NOT IN (
    -- this subquery returns a set of IDs corresponding to non-vegitarian recipes.
    select
      id 
    from
      recipes,
      ingredient_in_recipe,
      ingredients
    where
      ingredient_in_recipe.recipe_id = recipes.id
    and
      ingredient_in_recipe.ingredient_id = ingredients.id
    and
      ingredients.vegetarian <> 1
  );

从性能的角度来看,我建议不要使用相关子查询,除非绝对必要。谢谢,这很好用。我以前没有使用过“不存在”或“不存在”,所以这是一个很好的解决方案。有关更详细的解释,请参见@Bret的答案。在这种情况下,使用=0而不是1会有问题吗?我确信素食者将为0 false或1 true。是的,最好使用0 Yes,替代查询也可以。这会稍微快一点,对吗?我不确定是否有区别。它将在没有任何限制的情况下工作。在任何一种情况下,我都会在配方中的配料中创建索引,在创建表时,我使用BOOL数据类型(转换为TINYINT1)在vegetrian上创建索引。至少,我相当肯定它是这样做的。无论如何,我们都会考虑这两种数据类型。这里有这样一句话:BOOL,BOOLEAN这些类型是TINYINT1的同义词。零的值被认为是错误的。非零值被认为是真的。这并不能完全起作用,因为查询中没有包含表配料。此表对配料和食谱之间的多对多关系进行排序。配料表不包含配方id字段,它位于配方中的配料中。我认为@JuniorCompressor的答案需要内部连接。
select
  *
from
  recipes
where
  id NOT IN (
    -- this subquery returns a set of IDs corresponding to non-vegitarian recipes.
    select
      id 
    from
      recipes,
      ingredient_in_recipe,
      ingredients
    where
      ingredient_in_recipe.recipe_id = recipes.id
    and
      ingredient_in_recipe.ingredient_id = ingredients.id
    and
      ingredients.vegetarian <> 1
  );