1

多くのWorkoutモデルを持ち、それらに属するモデルがありEquipmentます。Equipment私はいくつかのIDの配列を持っています。IDの配列のいずれかに一致するものが割り当てられてWorkoutsいないものをすべて見つけたいと考えています。EquipmentEquipment

したがって、割り当てられた機器 ID に、またはarray = [2,3,5]が含まれていないすべてのワークアウトを検索したい場合は、 .235

編集:

Workout.joins(:equipment).where("equipment.id not in(?)",[2,3,5]).uniq

のインスタンスが 5 つあると仮定するとEquipment、上記のコードはequipment.ids1と(良い) を含むワークアウトを返しますが、4たとえば= ,などの部分一致も返します。Workoutsequipment.id[1,2][1,2,3]

4

3 に答える 3

2

クエリが返す結果セットを考えると役立ちます。

Workout.joins(:equipment).where("equipment.id not in(?)",[2,3,5]).uniq

関連するすべての機器をワークアウトに参加させます。ワークアウトが 4 つの機器にリンクされている場合、そのワークアウトには 4 つの行が表示されます。where 句は、その 4 をより小さな数にフィルター処理するだけです。1 つが一致したからといって、それらをすべて消去することはできません。

代わりに、結合自体に条件を追加する必要があります。何かのようなもの

select workouts.*
left join equipments_workouts on workout_id = workouts.id and equipment_id in (2,3,5)
where equipment_id is null

正しいワークアウトを返す必要があります (機器が 0 のワークアウトも返す必要がありますが、それが考慮されているかどうかはわかりません)。

これは、「悪い」機器に参加しようとすることで機能します。これは左結合であるため、そのような行が見つからない場合でも、結果セットにはそのワークアウトの行が含まれますが、equipmnts_workouts の列はすべて null に設定されます。おまけとして、重複を排除する必要がなくなりました。

Activerecord には、このようなクエリを記述するための優れた方法がありません。ただし、 joins メソッドは任意の SQL フラグメントを受け入れます。

Workout.joins("left join equipment_workouts on workout_id = workouts.id and equipment_id in (2,3,5)").
        where("equipment_id is null")

sanitize_sqlそのSQLフラグメントを生成するのに役立つメソッドが見つかるかもしれません

于 2012-07-01T09:12:00.850 に答える
2
Workout.joins(:equipment).merge(Equipment.where("id not in(?)",[2,3,5])).uniq

また

Workout.joins(:equipment).where("equipments.id not in(?)",[2,3,5]).uniq

また、これを試すこともできます。機器を持たないすべてのワークアウトが見つかるはずです

Workout.includes(:equipment).where("equipments.id not in(?)",[2,3,5])
于 2012-07-01T00:05:21.500 に答える
0

これは改善することができますが、うまくいくはずです:

class Workout < ActiveRecord::Base
  scope :without_equipments, lambda{|ids| joins(:equipment).where("equipments.id not in (?)", ids.repeated_permutation(ids.size).map(&:uniq).uniq)}
end
Workout.without_equipments 2,3,5
于 2012-07-01T04:49:10.950 に答える