Rails大多数情况下的订单记录符合

时间:2017-08-17 15:15:41

标签: ruby-on-rails ruby performance

对关联中存在的元素进行排序,其中第一个元素将是最多选定关联中存在的元素。 换句话说,大多数订单中的订单元素存在于给定列表中。 这听起来很复杂,所以这里是工作示例,但速度超慢。

我们想对汽车进行分类,大多数司机都可以驾驶它们

complex

装载大约需要1秒,只有20辆车。 但现在我们有100辆汽车的情况,计算它需要几十年的时间。

我们如何编写sql请求来订购? 它不起作用,但显示了一些逻辑:

# we have some ids of driver seleted by user
dynamic_drivers_ids = [1,2,3,100,5]

@cars = Car.all.includes(:driving_levels)
@cars.sort_by {|e| (e.driving_level.map(&:driver_id) & dynamic_drivers_ids ).size * -1 }

Db表格如下:

Car.includes(:driving_levels).order("driving_level.id IN = ? AND driving_level.size", dynamic_drivers_ids)

3 个答案:

答案 0 :(得分:0)

左连接driving_levels怎么样,但只有那些在driver_id中有dynamic_drivers_ids的人(希望dynamic_drivers_ids不是来自用户,否则它是sql-injection-prone) )?然后你可以按照驾驶级别的计数进行分组和排序吗?

看起来像这样:

 Car
   .joins("LEFT OUTER JOIN driving_levels ON
           driving_levels.id = cars.driving_level_id AND 
           driving_level.driver_id IN (#{dynamic_drivers_ids})")
   .group(:id).order("COUNT(driving_levels.id)")

答案 1 :(得分:0)

首先,您应该在这里使用wherereferences

dynamic_drivers_ids = [1,2,3,100,5]

@cars = Car.includes(:driving_level).
            references(:driving_level).
            where(driving_level: {id: dynamic_drivers_ids})

这里会发生什么,它会加入表carsdriving_level,并且只提取driving_level条记录,这些记录包含这些ID(您不必这样做:e.driving_level.map(&:driver_id) & dynamic_drivers_ids) 。你不会再删除所有driving_level条记录了。 这应该会大大加快。

中学:按协会排序。最简单的方法是使用列来计算我们的关联,然后对它进行排序:

@cars = Car.select('COUNT(driving_levels.id) as driving_levels_size').
            includes(:driving_level).
            references(:driving_level).
            where(driving_level: {id: dynamic_drivers_ids}).
            group('cars.id, driving_levels.id').
            order('driving_levels_size')

这应该返回正确的顺序和正确的关联记录。

答案 2 :(得分:0)

如果driving_levels包含driver_id 1,2,3,100,5。

的记录,请尝试此操作
select_clause = <<~SQL
  cars.*,
  ( SELECT count(DISTINCT driver_id) FROM driving_levels
    WHERE driver_id IN (1,2,3,100,5)
       OR car_id=cars.id ) as driver_cnt
SQL

Car
  .select(select_clause)
  .order('driver_cnt DESC')
  .to_a