2017-08-17 6 views
-1

アソシエーション内に存在する順序要素は、最初に選択されたアソシエーションに存在する要素になります。 つまり、ほとんどのassosietionsによる要素の順序は、指定されたリストから存在します。 これは複雑なので、ここでは動作例ですが、スローなものです。Railsほとんどの条件で注文レコードを満たす

ほとんどのドライバーは彼らに

# 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 } 

を駆動させることができることにより、我々はそれが唯一の20台で、ロードする約1秒かかり、車をソートしたいです。 しかし、今では100台の車で状況があり、計算には数十年かかります。

どのように私たちはそのような注文のSQLリクエストを書くことができますか?

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

DBテーブルは次のようになります:そのは動作していない 、しかし、いくつかのロジックを示し

class Car 
    has_many :driving_levels 
    has_many :drivers, through: driving_levels 


class DrivingLevel 
    belongs_to :car 
    belongs_to :driver 

class Driver 
    has_many :driving_levels 
    has_many :cars, through: driving_levels 
+0

あなたのデータベースとは何ですか? –

+0

'cars belongs_to driving_level'と思われます。ですから、 'driving_level.map(&:driver_id)'を見るのは奇妙です。モデルコードを提供してください。 –

+0

テーブル – GEkk

答えて

0

dynamic_drivers_idsdriver_idを有するもの左程度参加driving_levelsだけを(希望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)") 
+0

配列をSQL文字列に挿入できるかどうかわかりません: – GEkk

+0

はい、間違いありません編集中 –

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に参加しますし、これらのIDを持つdriving_levelレコードのみを引き出します(あなたはする必要はありません:e.driving_level.map(&:driver_id) & dynamic_drivers_ids)。あなたはもうdriving_levelのレコードをもう一本引き上げません。 これは大幅にスピードアップするはずです。

セカンダリ:関連付け順。これはあなたに正しい順序とassocationsの正しいレコードを返す必要があります

@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') 

:最も簡単な方法は、当社の関連付けをカウントし、カラム、およびそれ以上の順序を使用することです。

+0

PG :: UndefinedColumn:ERROR:列 "driving_levels_size"が存在しません – GEkk

0

driving_levelsdriver_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 
関連する問題