使用AREL编写"不在"sql查询中

sno*_*ard 6 ruby-on-rails arel

我的范围定义如下:

scope :ignore_unavailable, lambda { 
  where([ "Item.id NOT IN (SELECT id FROM Cars WHERE Cars.status = 'NA'" ])
}
Run Code Online (Sandbox Code Playgroud)

目前它使用硬编码表名.如何使用像Arel这样的框架来改进它?将在这里感谢任何帮助.

我在Rails 3.2上

br3*_*3nt 10

由于任务描述使用AREL请求答案,我提出以下内容:

class Car
  scope :available, -> { where(arel_table[:status].not_in(['NA'])) }
end

class Item
  scope :available, -> { where(:id => Car.available) }
end
Run Code Online (Sandbox Code Playgroud)

sql应该类似于以下内容:

SELECT [items].*
FROM [items]
WHERE [item].[id] IN (
    SELECT [cars].[id]
    FROM [cars]
    WHERE [car].[status] NOT IN ('NA')
  )
Run Code Online (Sandbox Code Playgroud)

显然,轨道4具有not范围,因此这是轨道3的解决方案.

上面的代码有两个好处:

  • 它执行单个查询
  • 表列是正确的命名空间(与使用原始sql时不同)


ush*_*sha 3

如果您使用的是 Rails 4,一种方法是

scope :ignore_unavailable, lambda {
  where.not(id: Car.where(:status => "NA").pluck(:id))
}
Run Code Online (Sandbox Code Playgroud)

适用于导轨 3

scope :ignore_unavailable, lambda {
  where("id not in (?)", Car.where(:status => "NA").pluck(:id))
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。这很棒!但有一个问题,我们不会在这里执行两个 SQL 查询,而不是像原始情况那样执行一个 SQL 查询吗? (2认同)