我想做类似的事情:
SELECT "recipes"."id"
FROM "recipes"
INNER JOIN "groups" ON "groups"."recipe_id" = "recipes"."id"
INNER JOIN "steps" ON "steps"."group_id" = "groups"."id"
INNER JOIN "steps_ingredients_memberships" ON "steps_ingredients_memberships"."step_id" = "steps"."id"
INNER JOIN "ingredients" ON "ingredients"."id" = "steps_ingredients_memberships"."ingredient_id"
WHERE (ingredients.id IN (5, 6) AND ingredients.id IN (10, 11))
LIMIT 10
但是此请求返回0行...
我知道此请求无法正常工作,但找不到解决方法
我想获取包含成分5 OR
6 AND
10 OR
11。
像这样思考:
5 = tomatoes
6 = big tomatoes
10 = potatoes
11 = big potatoes
我想要西红柿OR
大西红柿AND
土豆OR
大土豆的“食谱”。
采用的解决方案
因为成分可以是随机的,所以我写了一个范围:
scope :ingredients_filtering, lambda { |ingredients|
return if ingredients.nil?
queries = []
ingredients.each do |ingredient|
related_ids = ingredient.related_ids.uniq.join(', ')
queries << "BOOL_OR(ingredients.id IN (#{related_ids}))"
end
group(:id).having(queries.join(' AND '))
}
谢谢大家! :)
答案 0 :(得分:2)
您要聚合。按配方分组,看看它是否具有所需的成分。
$("#inputBox").on("input", throttle(2000, function(evt) {
myFunctionToThrottle(evt);
}));
答案 1 :(得分:1)
要在@MrYoshiji's评论Here上进行扩展,我们可以使它更加“肮脏”,如下所示:
ingredients_table = Ingredient.arel_table
ingredient_list1 = [5,6]
ingredient_list2 = [10,11]
condition = Arel::Nodes::NamedFunction.new(
'BOOL_OR',[ingredients_table[:id].in(ingredient_list1)]
).and(
Arel::Nodes::NamedFunction.new(
'BOOL_OR',[ingredients_table[:id].in(ingredient_list2)]
)
)
recipes = Recipe.joins(groups: {
steps: {
steps_ingredients_memberships: :ingredients
}
})
.group('recipes.id')
.having(condition)
这将产生类似于链接答案的SQL :(由@ThorstenKettner提供)例如
SELECT recipes.*
FROM recipes
JOIN groups ON groups.recipe_id = recipes.id
JOIN steps ON steps.group_id = groups.id
JOIN steps_ingredients_memberships ON steps_ingredients_memberships.step_id = steps.id
JOIN ingredients ON ingredients.id = steps_ingredients_memberships.ingredient_id
GROUP BY
recipes.id
HAVING
BOOL_OR(ingredients.id IN (5, 6)) AND
BOOL_OR(ingredients.id IN (10, 11))
但是,它提供了以更有效的方式更改ingredient_list1
和ingredient_list2
的灵活性,而无需担心转义等问题。
顺便说一句以发表您的评论:
“我放置了ruby-on-rails标签,因为如果在ruby-on-rails中有解决方案,那就更好了,但我认为不是...”
arel
可以汇编您可以想象的任何查询(它也可以汇编无效/分段的SQL)。如果它是有效的,则SQL ActiveRecord
可以运行它,因此,如果您使用的是rails且查询问题肯定像您一样包含ruby-on-rails标记。
更新(根据您发布的解决方案),但使用arel
而不是字符串串联
scope :ingredients_filtering, lambda { |ingredients|
return unless ingredients
ingredients_table = Ingredient.arel_table
conditions = ingredients.map do |ingredient|
Arel::Nodes::NamedFunction.new(
'BOOL_OR',[ingredients_table[:id].in(ingredient.related_ids)]
)
end.reduce(&:and)
group(:id).having(conditions)
}
答案 2 :(得分:0)
使用GROUP BY
和HAVING
:
SELECT "recipes"."id"
FROM "recipes"
INNER JOIN "groups" ON "groups"."recipe_id" = "recipes"."id"
INNER JOIN "steps" ON "steps"."group_id" = "groups"."id"
INNER JOIN "steps_ingredients_memberships" ON "steps_ingredients_memberships"."step_id" = "steps"."id"
INNER JOIN "ingredients" ON "ingredients"."id" = "steps_ingredients_memberships"."ingredient_id"
GROUP BY "recipes"."id"
HAVING COUNT(CASE WHEN ingredients.id IN (5, 6) THEN 1 END) > 0
AND COUNT(CASE WHEN ingredients.id IN (10, 11) THEN 1 END) > 0