Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/53.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Rails、ActiveRecord、嵌套模型上具有多个连接的复杂查询_Sql_Ruby On Rails_Postgresql_Activerecord - Fatal编程技术网

Sql Rails、ActiveRecord、嵌套模型上具有多个连接的复杂查询

Sql Rails、ActiveRecord、嵌套模型上具有多个连接的复杂查询,sql,ruby-on-rails,postgresql,activerecord,Sql,Ruby On Rails,Postgresql,Activerecord,一段时间以来,我一直试图通过ActiveRecord创建这个复杂的查询,但没有任何效果。我正在尝试为指定用户获取具有最高训练设置重量的训练,并根据重量进行训练和订购 模型看起来像是删除了错误的字段: Workout belongs_to :user has_many :workout_exercises WorkoutExercises belongs_to :workout belongs_to :exercise has_many :workout_sets Work

一段时间以来,我一直试图通过ActiveRecord创建这个复杂的查询,但没有任何效果。我正在尝试为指定用户获取具有最高训练设置重量的训练,并根据重量进行训练和订购

模型看起来像是删除了错误的字段:

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
例如,假设使用以下数据,练习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
这实际上抛出了一个异常。我已经尝试了很多关于这个查询的方法,但是仍然无法让它工作。我最终尝试在纯SQl中使用以下查询(不包括user.id子句)执行此操作,但得到的结果集为空:

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")
WITH joined_table AS (
    SELECT workout_sets.weight AS weight, 
        workouts.user_id AS user_id, 
        workouts.id AS workout_id, 
        workout_sets.id AS workout_set_id,
        workout_exercises.exercise_id AS exercise_id
    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       
    ORDER BY workout_sets.weight DESC
    ),

result_set AS (
    SELECT MAX(x.workout_id) AS workout_id, 
           x.user_id, 
           x.weight, 
           x.workout_set_id, 
           x.exercise_id
    FROM joined_table x
    JOIN (SELECT p.user_id, MAX(weight) as weight
        FROM joined_table p
        GROUP BY p.user_id) y 
    ON y.user_id = x.user_id AND y.weight = x.weight
    GROUP BY x.user_id, x.weight, x.workout_set_id, x.exercise_id
    ORDER BY x.weight DESC)

SELECT workouts.*, 
       result_set.weight, 
       result_set.workout_set_id, 
       result_set.exercise_id
FROM workouts, result_set
WHERE workouts.id = result_set.workout_id 
    AND result_set.exercise_id = 1 -- arbitrary exercise ID
    AND workouts.user_id IN (1,2) -- arbitrary set of user IDs

给定一个练习实例练习,您可以选择不同的训练、使用:workout\u exercises和:workout\u set嵌套联接、按练习\u id过滤以及按训练\u set排序。权重如下:

Workout.joins(:workout_exercises => :workout_sets).
  where('workout_exercises.exercise_id' => exercise.id).
  order('workout_sets.weight DESC').
  uniq

经过大量的工作和研究,这是产生所需结果集的查询:

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")
WITH joined_table AS (
    SELECT workout_sets.weight AS weight, 
        workouts.user_id AS user_id, 
        workouts.id AS workout_id, 
        workout_sets.id AS workout_set_id,
        workout_exercises.exercise_id AS exercise_id
    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       
    ORDER BY workout_sets.weight DESC
    ),

result_set AS (
    SELECT MAX(x.workout_id) AS workout_id, 
           x.user_id, 
           x.weight, 
           x.workout_set_id, 
           x.exercise_id
    FROM joined_table x
    JOIN (SELECT p.user_id, MAX(weight) as weight
        FROM joined_table p
        GROUP BY p.user_id) y 
    ON y.user_id = x.user_id AND y.weight = x.weight
    GROUP BY x.user_id, x.weight, x.workout_set_id, x.exercise_id
    ORDER BY x.weight DESC)

SELECT workouts.*, 
       result_set.weight, 
       result_set.workout_set_id, 
       result_set.exercise_id
FROM workouts, result_set
WHERE workouts.id = result_set.workout_id 
    AND result_set.exercise_id = 1 -- arbitrary exercise ID
    AND workouts.user_id IN (1,2) -- arbitrary set of user IDs

我试过了,但没用。Postgres对顺序要求严格,这使得select语句中的列太多,这意味着默认情况下无法选择ID。我已经用你的建议更新了我的问题。很好的问题示例可供学习。自我回答也很好。我想知道也许训练集的数量和重量可以作为训练的属性。这意味着每一次运动都有一个固定的重量。你失去了改变训练集重量的能力,但是如果你不需要改变它们,它会大大简化你的SQL。