Intereting Posts
Как получить базу данных SQL в R с локального хоста? ORDER BY "ENUM field" в MYSQL Каковы некоторые полезные инструкции SQL / шаблоны использования, которые должны быть известны всем разработчикам, которые могут коснуться задней стороны проекта? Присоедините 3 таблицы и фильтр Ошибка при отправке отчета JOIN или Коррелированный подзапрос с условием существования, который лучше MySQL: получение количества и суммы целочисленных значений в нескольких столбцах Возврат select * result в функции postgres Обнаружение и обработка, когда запрос базы данных идет не так Может ли ActiveRecord создавать таблицы за пределами миграции? Группа за исключением определенных значений Загруженные файлы Docx становятся поврежденными Предотвращать атаки SQL-инъекций в программе Java Определение функции PostgreSQL в SQuirreL: неисчерпаемая строка в долларах MYSQL выбирает значения DISTINCT в двух столбцах

Поверните SQL-запрос в ActiveRecord Relation

Как включить следующий SQL-запрос в отношение ActiveRecord, чтобы я мог расширять его с помощью областей?

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 ), sub_query AS ( SELECT p.user_id, MAX(weight) as weight FROM joined_table p GROUP BY p.user_id ), 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 sub_query 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 

Это что-то, что я должен был бы предпринять с прямым АРЕЛОМ?

Я попытался разбить его на области / подзапросы, но выборки в подзапросах приводятся в охватывающем запросе, таким образом бросая ошибки PostgreSql, потому что столбец не указан в операторах GROUP BY или ORDER BY в заключении.

Обновление: вы правы в своем предположении, что это PostgreSql. Я попытался выполнить ваш запрос, но он выдает сообщение PG::Error: ERROR: column "rownum" does not exist , как для прямого запроса, так и для эквивалентности ActiveRecord.

Однако, когда я обертываю запрос в отдельный запрос, он работает. Я предполагаю, что ROW_NUMBER () не создается до тех пор, пока выбор не будет проецирован на набор данных. Поэтому работает следующий запрос:

 SELECT workouts.*, t.weight, t.workout_set_id, t.exercise_id, t.row_num FROM workouts, (SELECT workouts.id as workout_id, workout_sets.weight as weight, workout_sets.id AS workout_set_id, workout_exercises.id AS exercise_id, ROW_NUMBER() OVER ( PARTITION BY workouts.user_id ORDER BY workout_sets.weight DESC, workouts.id DESC ) row_num FROM workouts JOIN workout_exercises ON workout_exercises.workout_id = workouts.id JOIN workout_sets ON workout_sets.workout_exercise_id = workout_exercises.id) as t WHERE workouts.id = t.workout_id AND t.row_num = 1 

Который мне удалось массировать в следующее:

  selected_fields = <<-SELECT workouts.id AS workout_id, workout_sets.weight AS weight, workout_sets.id AS workout_set_id, workout_exercises.id AS exercise_id, ROW_NUMBER() OVER ( PARTITION BY workouts.user_id ORDER BY workout_sets.weight DESC, workouts.id DESC) as row_num SELECT Workout.joins(", (#{Workout.joins(:workout_exercises => :workout_sets).select(selected_fields).to_sql}) as t").select("workouts.*, t.*").where("workouts.id = t.workout_id AND t.row_num = 1").order("t.weight DESC") 

Но, как вы можете сказать, это очень хакерский и массивный запах кода. Любая идея о том, как реорганизовать это?

По-видимому, вы пытаетесь получить самую последнюю информацию о тренировке (самый высокий идентификатор), которая соответствует максимальному весу для каждого пользователя. Также кажется, что вы используете PostgreSQL (у MySQL нет CTE), исправьте меня, если я ошибаюсь.

Если это так, вы можете использовать функции окна и упростить свой запрос:

 SELECT * FROM ( SELECT workouts.*, workout_sets.weight, workout_sets.id AS workout_set_id, workout_exercises.id AS exercise_id, ROW_NUMBER() OVER ( PARTITION BY workouts.user_id ORDER BY workout_sets.weight DESC, workouts.id DESC ) as rowNum FROM workouts JOIN workout_exercises ON workout_exercises.workout_id = workouts.id JOIN workout_sets ON workout_sets.workout_exercise_id = workout_exercises.id ) t WHERE rowNum = 1 

Который в ActiveRecord может быть записан как:

 selected_fields = <<-SELECT workouts.*, workout_sets.weight, workout_sets.id AS workout_set_id, workout_exercises.id AS exercise_id, ROW_NUMBER() OVER ( PARTITION BY workouts.user_id ORDER BY workout_sets.weight DESC, workouts.id DESC) as rowNum SELECT subquery = Workout.joins(:workout_exercises => :workout_sets). select(selected_fields).to_sql Workout.select("*").from(Arel.sql("(#{subquery}) as t")) .where("rowNum = 1")