如何將以下SQL查詢轉換爲ActiveRecord關係,以便可以使用範圍對其進行擴展?將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
這是我要嘗試直ARel嗎?
我試過把它分解成作用域/子查詢,但子查詢上的選擇最終在封閉查詢中,因此拋出PostgreSql錯誤,因爲在GROUP BY或ORDER BY中未指定列聲明。
更新: 你假設它是PostgreSQL是正確的。我嘗試了你的查詢,但是它爲直接查詢和ActiveRecord等價物拋出了一個PG::Error: ERROR: column "rownum" does not exist
。
但是,當我將查詢包裝在單獨的查詢中時,它起作用。我假設ROW_NUMBER()直到select被投影到數據集之後才被創建。所以下面的查詢工作:
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")
但是,正如你所知道的,這是非常哈克,是一個龐大的代碼味道。任何想法如何重構?
此查詢使用CTE的直接不由ActiveRecord或Arel支持。如果你重構這個以避免CTE,你可以用它們中的任何一個來做到這一點。 – PinnyM 2013-05-01 20:10:42
你可以驗證你是否使用PostgreSQL? – PinnyM 2013-05-01 20:51:53
我也需要這個功能! – 2014-03-26 07:00:32