ruby-on-rails - Postgres:来自多个连接的总和导致值超出预期
问题描述
我有 3 个表:invoices、invoice_payments、invoice_credit_notes。我想获取所有支付总额小于grand_total
发票表中金额的发票。
在发票模型中
has_many :invoice_payments
has_many :invoice_credit_notes
在 invoice_payments 模型中
belongs_to :invoice
在 invoice_credit_notes 模型中
belongs_to :invoice
invoice_payments
有amount
和discount
领域。
invoice_credit_notes
里面有amount
字段。
这是我想出的:
scope :unpaid, ->{left_outer_joins(:invoice_payments, :credit_note_invoices)
.having('(COALESCE(SUM(invoice_payments.amount + invoice_payments.discount), 0) + COALESCE(SUM(credit_note_invoices.amount), 0)) < ROUND(invoices.grand_total, 0)')
.group('invoices.id')}
但是我的解决方案存在问题,因为可能有多个 invoice_payments 或 invoice_credit_notes(COALESCE(SUM(invoice_payments.amount + invoice_payments.discount), 0) + COALESCE(SUM(invoice_credit_notes.amount), 0)
返回的金额高于实际支付的金额。这很可能是因为正在连接多个表。
那么,如何克服这个问题呢?
解决方案
该语句生成这个(简化的)查询:
select sum(p.amount+ p.discount)+ sum(n.amount)
from invoice i
left join invoice_payments p on p.invoice_id = i.id
left join invoice_credit_notes n on n.invoice_id = i.id
group by i.id;
这两个连接创建了所有行的笛卡尔积,因此invoice_payments
被多次求和。您应该在单独的派生表(子查询)中计算聚合:invoice_credit_notes
invoice_id
amounts
select p.sum+ n.sum
from invoice i
left join (
select invoice_id, sum(amount+ discount)
from invoice_payments
group by invoice_id
) p on p.invoice_id = i.id
left join (
select invoice_id, sum(amount)
from invoice_credit_notes
group by invoice_id
) n on n.invoice_id = i.id
我希望您可以轻松地将其翻译成 ruby。
推荐阅读
- angular - 在 Liferay 中调整 Angular 应用程序时出错
- python - 使用双缓冲时的滚动条动画
- python - 计算值在熊猫数据框中的列中的每个备用实例中出现的次数
- javascript - Sequelize - 请手动安装 mysql2 包
- algorithm - 传统的 Fletcher/Adler 校验和算法是最优的吗?
- javascript - 在 switch 中使用 lint 的问题 - 使用三元运算符的情况
- reactjs - Map 不是 React 返回中的函数
- c++ - 如何在编译时创建一个带有 string_views 序列的 constexpr 数组?
- r - R:从数据框中为字符行赋值
- postgresql - 在 postgresql 中使用 row_number() 后如何选择行