如何在函数而不是数据库列上运行where子句?

时间:2013-12-15 18:22:20

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord

在我的Invoice模型中,我正在尝试获取所有未结发票:

class Invoice < ActiveRecord::Base

  has_many :payments

  def self.outstanding
    where("outstanding_amount != 0")
  end

  private

  def outstanding_amount
    total - payments.to_a.sum(&:amount_in_cents)
  end

end

但这不起作用,因为我没有数据库列outstanding_amount。有没有办法在函数而不是数据库字段上运行where子句?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

您需要将表达式作为having子句的一部分传递。我会推迟使用RoR向导来获取活动记录语法,但是你的最终查询应该类似于:

select ...
from ... join payments on ...
where ...
group by ...
having total != sum(payments.amount)

如果大多数行不平衡(不太可能),则替代方案可以是相关子查询:

select ...
from ...
where ...
and total != (select sum(amount) from payment where ...)

(如果大多数行不平衡,请不要执行上述操作,因为性能会很糟糕。)

最后一个替代方案(我实际上建议)是维护paid列 - 理想情况下,尽管不一定,使用触发器。然后你可以使用:

select ...
from ...
where ...
and total != paid

更好的是,你可以改写后者,如:

where total - paid != 0

然后在(total - paid) where (total - paid != 0)上添加部分索引,以获得最佳效果。