我有一个餐厅表,一个美食表和一个连接多对多的联接表。我想找到一个匹配两种特定美食的餐厅,即找到联接表中列出的与“美食1”和“美食2”相关的餐厅。
我可以将它们和包含在一起的东西一起破解,但是感觉好像在使用ActiveRecord构建查询时肯定缺少一些直接而明显的东西。
Restaurant
ID| Name
1 | McDonalds
2 | Taco Bell
Cuisine
ID| Style
1 | American
2 | Mexican
3 | Fast Food
Restaurant_Cuisines
ID | Restaurant_ID | Cuisine_ID
1 | 1 | 1
2 | 1 | 3
3 | 2 | 2
4 | 2 | 3
我希望能够查询同时提供American&Fast Food的餐厅,这会让我回想起McDonalds,但没有Taco Bell,因为Taco Bell提供Fast快餐,但没有美国人。
答案 0 :(得分:2)
我可以想到以下查询,它可能不是最优化的解决方案,但它给出了正确的答案,并且可以指导获得最佳答案的方向。
rest_ids = Restaurant_Cuisines.where(Cuisine_ID: 1).pluck(:Restaurant_ID) && Restaurant_Cuisines.where(Cuisine_ID: 3).pluck(:Restaurant_ID)
Restaurant.where(id: rest_ids)
如果需要概括:
def specific_restaurant(cuisine_ids)
ids = cuisine_ids.map { |id| Restaurant_ID.where(Cuisine_ID: id).pluck(:Restaurant_ID) }.reduce(:&)
Restaurant.where(id: ids) if ids.present?
end
绝对是N+1
,其中N
是cuisine_ids
,但是如果N
受限制/很少,则不会造成伤害。
更新-最后,一次查询!
def specific_restaurant(cuisine_ids)
ids = RestaurantCuisine.where(cuisine_id: cuisine_ids).group(:restaurant_id).having("count(*) = #{cuisine_ids.count}").pluck(:restaurant_id)
Restaurant.where(id: ids) if ids.present?
end
答案 1 :(得分:0)
假设您具有外键的ID,则可以使用joins
并像这样传递联接表的ID:
cuisine_ids = Cuisine.where(Style: ['American', 'Mexican']).pluck(:id)
restaurants = Restaurant.joins(:cuisines).where(cuisines: {id: cuisine_ids})