【问题标题】:Complex Rails/Postgres SQL optimization复杂的 Rails/Postgres SQL 优化
【发布时间】:2013-05-09 12:46:00
【问题描述】:

餐厅 has_many 菜

Dish
has_many Photo

Photo
belongs_to Dish

Restaurant 1
  Dish 1
    Photo 1   May 9, 1:00 PM
  Dish 2
    Photo 2   May 9, 2:00 PM
  Dish 3
    Photo 3   May 9, 3:00 PM

Restaurant 2
  Dish 4
    Photo 4   May 9, 1:00 PM
  Dish 5
    Photo 5   May 9, 2:00 PM
  Dish 6
    Photo 6   May 9, 3:00 PM

我正在尝试检索最新的 50 张照片,每家餐厅限制为 2 张菜肴照片。鉴于上述数据,我将能够检索 id 为 2, 3, 5, and 6 的照片

至少可以说我目前的实现很丑。

hash = {}
bucket = []
Photo.includes(:dish => [:restaurant]).order("created_at desc").each do |p|
  restaurant_id = p.dish.restaurant.id
  restaurant_count = hash[restaurant_id].present? ? hash[restaurant_id] : 0
  if restaurant_count < 2
    bucket << p
    hash[restaurant_id] = restaurant_count + 1
  end
  # if you've got 50 items short circuit.
end

我不禁觉得有一个更有效的解决方案。任何想法将不胜感激:-)。

【问题讨论】:

  • 即使在纯 SQL 中,这也不是简单的逻辑。您最好维护某种专门的队列结构,该结构始终维护这 50 张照片的列表。然后,当您将新照片排入队列时,您可以执行每家餐厅 2 次的限制。显然,这将针对少写多读进行优化。
  • 是的,这是我的下一步,因为我对子查询一无所知。
  • 如果您想通过谷歌搜索来设置 SQL,如下所示:books.google.com/… 可能是最好的方法...

标签: sql ruby-on-rails ruby ruby-on-rails-3 postgresql


【解决方案1】:

应该有一种“分组”查询的方法,但至少以下方法更简单一些:

def get_photo_bucket
  photo_bucket = restaurant_control = []
  Photos.includes(:dish => [:restaurant]).order("created_at desc").each do |photo|
    if photo_bucket.count < 50 && restaurant_control.count(photo.dish.restaurant.id) < 2
      photo_bucket << photo
      restaurant_control << photo.dish.restaurant.id
    end
  end
  photo_bucket
end

【讨论】:

  • 不幸的是,这只会返回每家餐厅最新的两道菜,而不是最近的 50 道菜,每道菜最多两道。
  • 对不起@mikeryz,我误解了你的限制。我已经编辑了答案。
猜你喜欢
  • 2013-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-17
相关资源
最近更新 更多