ruby-on-rails 将SQL语句转换为rails命令

zbwhf8kr  于 2022-11-26  发布在  Ruby
关注(0)|答案(1)|浏览(201)

我有一种情况,我只需要从一个特定的活动记录查询响应中提取几个记录。

@annotations = Annotations.select('*', ROW_NUMBER() OVER (PARTITION BY column_a) ORDER BY column_b)

上面是一个查询,其中@annotations是活动记录响应,我想在它上面应用下面的逻辑。有没有更好的方法用rails的方式编写下面的逻辑?

with some_table as
(
 select *, row_number() over (partition by column_a order by column_b) rn
 from the_table
)
select * from some_table
where (column_a = 'ABC' and rn <= 10) or (column_b <> 'AAA')
pod7payv

pod7payv1#

ActiveRecord在其高级API中不提供CTE;但是,只要稍微使用Arel,我们就可以将其作为FROM子句中的子查询

annotations_table = Annotation.arel_table 
sub_query = annotations_table.project(
  Arel.star,
  Arel.sql('row_number() over (partition by column_a order by column_b)').as(:rn)
)
query = Arel::Nodes::As.new(sub_query, Arel.sql(annotations_table.name))

Annotation.from(query).where(
  annotations_table[:column_a].eq('ABC').and(
    annotations_table[:rn].lt(10)
  ).or(annotations_table[:column_b].not_eq('AAA'))
)

结果将是Annotation对象的集合,这些对象使用您的CTE和您描述的过滤器。
SQL语句:

select annotations.* 
from (
 select *, row_number() over (partition by column_a order by column_b) AS rn
 from annotations
) AS annotations
where (annotations.column_a = 'ABC' and annotations.rn <= 10) or (annotations.column_b <> 'AAA')

备注:

  • 通过一点额外的工作,我们可以使其成为CTE,但在这种情况下似乎不需要
  • 我们也可以使用一堆hack来将这个row_number() over (partition by column_a order by column_b)转换为Arel,但它似乎与这个问题无关。

相关问题