如何在Rails中组合内连接和左外连接

时间:2014-11-20 00:12:49

标签: sql ruby-on-rails postgresql

我有两个模型invoicepayments。它们之间的关系为invoice has_many payments

我使用以下左外联接返回所有尚未支付的发票:

result1 = Invoice.includes(:payments).where(:payments => { :id => nil })

我也对所有已部分支付的发票感兴趣。要返回那些我使用内连接:

result2 = Invoice.joins(:payments).group("transfers.id").having("sum(payments.amount) < invoice.amount")

我现在想结合两个结果,即我希望所有未支付或未全额支付的发票。我知道我可以做result = result1 + result2。但是,这不会返回ActiveRecord对象。有没有办法在单个查询中组合这两个查询?

我使用Rails 4.1和PostgreSQL

2 个答案:

答案 0 :(得分:3)

我相信你是正确的,你不能让ActiveRecord生成除了内连接之外的任何东西而不用自己编写它。但我不会在此上下文中使用includes,因为它确实会导致ActiveRecord生成不同的连接,即“实现细节” - 它的基本目的是加载相关的模型,不一定是你想要的。

在您提出的解决方案中,我不明白您为什么要将invoices.idpayments.id分组 - 这似乎打败了分组的目的。

你可以做类似下面的事情,虽然我不能说这似乎更像是Rails-ish。

Invoice.joins("LEFT JOIN payments ON payments.transfer_id = invoices.id")
  .select("invoices.id, SUM(payments.amount) AS total_paid")
  .group("invoices.id")
  .having("SUM(payments.amount) IS NULL OR SUM(payments.amount) < invoices.amount")

这将返回仅包含id字段和total_paid字段集的Invoice对象列表。如果您需要其他可用字段,请将它们添加到select语句和group语句中。

答案 1 :(得分:0)

我最后只做了LEFT OUTER JOIN。但是,Rails似乎不支持grouphavingincludes()生成的LEFT OUTER JOIN。因此,我必须手动构建连接,这实际上并不像Rails方式那样&#34;。

我的查询:

    Invoice.joins("LEFT JOIN payments ON payments.transfer_id = invoices.id").group("invoices.id, payments.id").having("((payments.id IS NULL) OR (sum(payments.amount) < invoices.amount))")

更新:这不会按预期工作。请参阅接受的答案。