有效地返回连接所有标签的对象

时间:2014-02-26 16:43:42

标签: mysql sql

我正在运行一个基本的标记式系统,我想知道我的查询效率如何。

我的具体使用案例涉及使用recipe通过ingredients对象标记requirement个对象,该对象具有recipe_idingredient_id

食谱,成分和要求都完全由user孤立。

我希望能够返回用户的食谱,其中包含给定集合中的所有成分。

我这样做的方式,给出ingredient_ids (1,2)user_id 1 的列表,就像这样:

SELECT `recipes`.* FROM `recipes` 
  WHERE `recipes`.`id` IN (
    SELECT `requirements`.`recipe_id` 
      FROM `requirements` 
      WHERE `requirements`.`ingredient_id` IN (1, 2) 
       AND `requirements`.`user_id` = 1
      GROUP BY `requirements`.`recipe_id` 
      HAVING COUNT(`requirements`.`recipe_id`) = 2)

这是返回我需要的数据,但我担心它的性能。子查询看起来不太好,因为它使用ingredient_id 1或2抓取所有需求,按配方对它们进行分组,然后将它们计数以匹配给定的数组大小,只需创建一个数组,以进一步查询配方ID。 / p>

但是requirements表可能是庞大的,因为每个条目管理食谱和成分之间可能存在n个平方的双向关系。因此,以这种方式查询整个表是没有意义的。

我错过了什么吗?

我经常听说IN和NULL相等比较比JOIN快得多,但当子查询的复杂性否定了速度节省时肯定不会这样做吗?

这似乎是一个非常简单的问题,我过度工程,你会如何改进它?

1 个答案:

答案 0 :(得分:0)

我没有你的数据库进行测试,抱歉,所以我不确定这是否会产生你想要的结果。但也许尝试加入requirements表而不是使用子查询,它将避免潜在的性能损失,并且只需要通常更清晰的代码。以下是我希望对您有用的信息:

SELECT `recipes`.`recipe_id`
FROM `recipes` AS rec
JOIN `requirements` AS req ON rec.`recipe_id` = req.`recipe_id`
WHERE `requirements`.`ingredient_id` IN (1, 2) 
AND `requirements`.`user_id` = 1
GROUP BY `recipes`.`recipe_id` 
HAVING COUNT(`requirements`.`ingredient_id`) = 2

如果您有任何疑问,请告诉我