私はこの複雑なクエリをしばらく作成しようとしてきましたが、ActiveRecord では役に立ちませんでした。workout_set.weight
指定されたユーザーとエクササイズで最高のワークアウトを取得し、体重で並べ替えようとしています。
モデルは次のようになります (誤ったフィールドは削除されています)。
Workout
belongs_to :user
has_many :workout_exercises
WorkoutExercises
belongs_to :workout
belongs_to :exercise
has_many :workout_sets
WorkoutSet
belongs_to :workout_exercise
weight
たとえば、次のデータを使用します (exercise_id が同じであると仮定します)。
Steve:
Workout 1:
weight: 500
Workout 2:
weight: 400
Mark:
Workout 1:
weight: 300
Workout 2:
weight: 350
予想される結果セットは次のようになります。
Steve's Workout 1
Mark's Workout 2
これは PostgreSql 上にあるため、制約は sqlite や MySql よりも厳しくなっています。
更新: 私は PostgreSql で実行しているため、DB はクエリの order_by セクションでより厳密です。以下は、わかりやすくするためにすべてを書き出した RSpec テストです。
it 'fetches the workout with the highest weight' do
workout = create(:workout_with_exercises, user: user)
workout2 = create(:workout_with_exercises, user: user)
workout.workout_exercises[0].workout_sets[0].weight = 200
workout.save
workout2.workout_exercises[0].workout_sets[0].weight = 100
workout2.save
expect(user.workouts.count).to eq 2
exercise = workout.workout_exercises[0]
max_workout = Workout.joins(workout_exercises: :workout_sets)
.where('workout_exercises.exercise_id = ?', exercise.id)
.order('workouts.id, workout_sets.weight DESC')
.select("workouts.id, workout_sets.weight")
.uniq
#max_workout = user.workouts.max_weight(workout.workout_exercises[0])
expect(max_workout).to eq [workout]
end
これは実際に # 例外をスローします。このクエリを使用してさまざまなことを試しましたが、まだ機能しません。次のクエリ(user.id句を除く)を使用してストレートSQlでそれを実行しようとしましたが、空の結果セットが得られました:
max_workout = Workout.find_by_sql("
SELECT workouts.*
FROM workouts,
(SELECT DISTINCT workouts.id AS workout_id, workout_sets.weight AS weight
FROM workouts
INNER JOIN workout_exercises ON workout_exercises.workout_id = workouts.id
INNER JOIN workout_sets ON workout_sets.workout_exercise_id = workout_exercises.id
WHERE workout_exercises.exercise_id = #{exercise.id}
ORDER BY workouts.id, workout_sets.weight DESC) AS myquery
WHERE workouts.id = myquery.workout_id")