【问题标题】:SQL Query UnclearSQL查询不清楚
【发布时间】:2015-09-27 20:26:12
【问题描述】:

我正在尝试创建一个返回一组特定寄存器的查询,但我尝试了多种方法,但都不起作用。

我有 4 个如下表:

recipe {
    idRecipe integer,
    name varchar(100)
}

recipeStep {
    idStep integer,
    idRecipe integer,
    instruction varchar(100)
}

recipeIngredient {
    idStep integer,
    idIngredient integer
}

ingredient {
    idIngredient integer,
    name varchar(100)
}
  • 一个配方可以有一个或多个步骤;
  • 一个步骤只能是一个配方的一部分;
  • 一个步骤可以有一种或多种成分;
  • 一种成分可以是一个或多个步骤的一部分;

过滤器将返回包含用户选择的成分的所有配方。可以说我想要所有包含所有食谱内涵的食谱 68,25,36,109。所以我来到了这个:

SELECT r.* 
  FROM recipe r, recipeStep rs, recipeIngredient ri 
 WHERE r.idRecipe = rs.idRecipe
   AND rs.idStep = ri.idStep
   AND ri.idIngredient in (68,25,36,109)

问题是这个查询返回所有包含这些成分的所有食谱,我只想要包含所有这些成分的所有食谱

【问题讨论】:

  • 您显示的查询可能返回每个配方的次数与它具有匹配的成分一样多 - 因此您可以按配方(id)分组并计算不同的成分以查看它们是否足够(4在你的情况下)。
  • @jkavalik。我正要给出同样的建议=)

标签: mysql join where


【解决方案1】:

一种方法是使用 group by 子句和 having 子句,将组限制为具有 4 种不同成分的组。

SELECT r.idRecipe, r.name
  FROM recipe r
  JOIN recipeStep rs ON r.idRecipe = rs.idRecipe
  JOIN recipeIngredient ri ON rs.idStep = ri.idStep
 WHERE ri.idIngredient IN (68,25,36,109)
GROUP BY r.idRecipe, r.name
HAVING COUNT(DISTINCT ri.idIngredient) = 4;

或者,您可以跳过 IN 谓词并在 having 子句中使用条件聚合:

SELECT r.idRecipe, r.name
  FROM recipe r
  JOIN recipeStep rs ON r.idRecipe = rs.idRecipe
  JOIN recipeIngredient ri ON rs.idStep = ri.idStep
GROUP BY r.idRecipe, r.name
HAVING SUM(CASE WHEN ri.idIngredient = 68  THEN 1 END) > 0
   AND SUM(CASE WHEN ri.idIngredient = 25  THEN 1 END) > 0
   AND SUM(CASE WHEN ri.idIngredient = 36  THEN 1 END) > 0
   AND SUM(CASE WHEN ri.idIngredient = 109 THEN 1 END) > 0;

这两个查询都允许添加额外的成分,只要配方中有四个强制性成分。如果您想要完全匹配,您可以在 where 子句中添加另一个条件。

【讨论】:

  • 我猜第二个查询效率不高,因为它不能在ri.idIngredient 上使用索引,所以它会进行全表扫描。
  • @jkavalik 这可能是真的,如果将 where 子句放回第二个查询中,它应该能够使用索引。我只是想展示另一种方式。
  • 这是一个非常有趣的,但如果你可以请添加 WHERE,并可能从 GROUP BY 中删除 r.name,因为它是冗余的并且也会减慢速度。 (在激活ONLY_FULL_GROUP_BY 的 5.6 之前需要它,但在没有它或在 5.7 中都不能检测功能依赖关系)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-11
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多