小编典典

如何通过使用Arel在带有'or'和'and'子句的SQL查询中正确添加括号?

sql

我正在使用Ruby on Rails 3.2.2,并且想生成以下SQL查询:

SELECT `articles`.* FROM `articles` WHERE (`articles`.`user_id` = 1 OR `articles`.`status` = 'published' OR (`articles`.`status` = 'temp' AND `articles`.`user_id` IN (10, 11, 12, <...>)))

通过使用arel这样

Article
 .where(
   arel_table[:user_id].eq(1)
   .or(arel_table[:status].eq("published"))
   .or(
     arel_table[:status].eq("temp")
     .and(
       arel_table[:user_id].in(10, 11, 12, <...>)
     )
  )
)

它生成以下内容( 注意 :方括号与第一个SQL查询不同):

SELECT `articles`.* FROM `articles` WHERE (((`articles`.`user_id` = 1 OR `articles`.`status` = 'published') OR `articles`.`status` = 'temp' AND `articles`.`user_id` IN (10, 11, 12, <...>)))

由于 我认为 后一个SQL查询不能像第一个那样“工作”, 因此我如何使用Arel (或者可能是其他方式) 来生成SQL查询作为第一个?

更新(评论后)

给定“工作”上方的SQL查询相同,但我仍然想生成与问题中的第一个完全相同的SQL查询(这样做的主要原因是,第一个SQL查询比第二个更易读一个使用较少并使用“显式”括号),如何使用Arel做到这一点?


阅读 158

收藏
2021-03-23

共1个答案

小编典典

我已经成功使用了以下宝石:Arel顶部的squeel,因此您不必弄乱它。因此,为了生成查询,您可以在Squeel中执行以下操作:

@articles = Article.
  where{
  ( user_id.eq(1) | status.eq('published') ) |
  ( user_id.in([10, 11, 12, '<...>']) & status.eq('temp') )
}

# since this is an ActiveRecord::Relation we can play around with it
@articles = @articles.select{ [ user_id, status ] }

# and you can also inspect your SQL to see what is going to come out
puts @articles.to_sql

查询越复杂,得到的宝石就越多。

2021-03-23