当前位置: 首页 > 面试题库 >

将SQL查询转换为ActiveRecord关系

云新知
2023-03-14
问题内容

如何将以下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是正确的。我尝试了您的查询,但是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")

但是,正如您所知道的那样,这非常骇人,并且有大量的代码味道。关于如何重构的任何想法?


问题答案:

您显然正在尝试获取与每个用户的最高体重相匹配的最新锻炼(最高ID)详细信息。似乎您正在使用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")


 类似资料:
  • 问题内容: 有很多问题可以帮助将特定的SQL查询转换为ActiveRecord查询。 是否有一些帮助/指导[在线]工具可以自动进行转换? 问题答案: 这是您正在寻找的工具:http : //www.scuttle.io/

  • 问题内容: 我想将以下SQL查询转换为Elasticsearch之一。谁能帮上忙 我尝试了以下方法: 但不确定我是否做对了,因为它无法验证结果。似乎要在聚合内添加查询。 问题答案: 假设您使用Elasticsearch 2.x,则有可能在Elasticsearch中 具有 -semantics。我不知道2.0之前的可能性。 您可以使用新的Pipeline Aggregation Bucket Se

  • 我有两个表,它们通过一个外键来维护它们之间的父子关系。查询如下所示。我想在使用jpa的同时使用标准版。所以有人可以帮助我使用标准版吗 表“child”的“notification\u id\u child”列是外键,并引用表“parent”的主键。

  • 问题内容: 多亏了Erwin Brandstetter在我之前的问题“具有has_many关系的订单”中的帮助,我的SQL查询才能正常工作。 如何将该SQL转换为ActiveRecords或AREL查询以在范围中使用? 我最近来的是在朋友的帮助下… …这给了我一个错误: 更新: 我之前的问题对相关的架构和查询有完整的描述。但是基本上Articles have_many Metrics和一个Metr

  • 问题内容: 我在SQL Server 2008中具有下表: 我需要创建以下输出的查询: 列可以固定为[Mitarbeiter1]-[Mitarbeiter5],因为每个Filiale的行数不能超过5行。 非常感谢您的帮助! 问题答案: 使用SQL Server 2008,将Pivot和Rank函数组合在一起,可以为每个雇员数量提供理想的结果。首先,我们为每个分支中的每个员工分配一个ID,从每个新分

  • 问题内容: 我有一个如下所示的表。我的问题是:如何将列转换为行?我正在使用Microsoft SQL Server 我需要像下面的操作 怎么做?谢谢 问题答案: 您的资料 询问 结果集