为了通过两个&QUOT总和的查询;的has_many"子表? [英] Order a query by the sum of two "has_many" sub-tables?

查看:146
本文介绍了为了通过两个&QUOT总和的查询;的has_many"子表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序,发票的has_many item_numbers 发票的has_many支付。每个发票有一个平衡,这是ItemNumber量的总和属性,支付金额少的总和属性

In my app, Invoice has_many item_numbers and Invoice has_many payments. Each invoice has a balance, which is the sum of the ItemNumber amount attributes, less the sum of the Payment amount attributes.

的平衡是很容易计算出发票的模式,但我想写通过平衡排序发票查询,这是证明更难做的ActiveRecord / SQL。

The balance is very easy to calculate in the invoice model, but I am trying to write a query that sorts invoices by balance and this is proving much harder to do in ActiveRecord/SQL.

我成功设法订购item_numbers与下面的​​查询总数(感谢丹尼尔Rikowski)的发票:

I have successfully managed to order the invoices on the total of the item_numbers with the following query (thanks Daniel Rikowski):

Invoice.where(user_id: 1, deleted: false, status: 'Sent')
       .joins(:item_numbers)
       .select('invoices.*, sum(item_numbers.amount)')
       .group('invoices.id')
       .order('sum(item_numbers.amount) asc')
       .limit(20)

我试图延长本与下面的平衡命令;

I have tried to extend this to order by the balance with the following;

Invoice.where(user_id: 1, deleted: false, status: 'Sent')
       .joins(:item_numbers)
       .joins("FULL OUTER JOIN payments ON payments.invoice_id = invoices.id")
       .select("invoices.*, sum(item_numbers.amount_with_gst) - COALESCE(sum(payments.amount), 0)")
       .group("invoices.id")
       .order("sum(item_numbers.amount_with_gst) - COALESCE(sum(payments.amount), 0) #{dir}")/

有两个问题与此查询。首先,它的窘况丑陋,二,这是行不通的。我用在支付表的完整外连接,因为不是所有的发票有付款,如果我用刚刚加入(:付款)没有支付任何发票被排除的结果。聚结放在那里,以应对空额。

There are two problems with this query. First, it's horrendously ugly, and second, it doesn't work. I used the full outer join on the payments table as not all invoices have a payment and if I used just joins(:payments) any invoice without a payment was excluded from the results. The COALESCE was put there to deal with null amounts.

查询接近,但说,有3 item_numbers和1付款(一个pretty的典型场景),支付金额将被减去导致平衡比实际量要少得多(通常一个负的3倍平衡量)。

The query comes close, but say there are 3 item_numbers and 1 payment (a pretty typical scenario), the payment amount will be subtracted 3 times resulting in a balance much less than the actual amount (and usually a negative balance).

这可能是pretty的清楚如何走出我的深度我。我已经投入了大量的精力投入到这个查询(约4个小时的阅读和失败的尝试),并不能很钉子了。我的数据库是PostgreSQL的。

It's probably pretty clear how out of my depth I am. I've put a lot of effort into this query (about 4 hours of reading and failed attempts) and can't quite nail it. My database is PostgreSQL.

推荐答案

您的问题被列相乘所致。想象一下,有一个付款和属于发票3 Item_numbers。的常规连接,其结果将是这样的:

Your problem is caused by columns multiplying. Imagine having one Payment and three Item_numbers belonging to a Invoice. The result of a regular join would be something like this:


| invoice.id | item_number.amount | payment.amount |
| 1          | 4                  | 5              |
| 1          | 7                  | 5              |
| 1          | 2                  | 5              |

因此​​,总和(payment.amount)将返回15,而不是5。要得到正确的总和,你必须直接获取和:

Because of this, sum(payment.amount) will return 15 and not 5. To get the correct sum, you have to fetch the sum directly:

Invoice.select('invoices.id, (SELECT SUM(item_numbers.amount) from item_numbers WHERE item_numbers.invoice_id = invoices.id) - (SELECT COALESCE(SUM(payments.amount),0) from payments WHERE payments.invoice_id = invoices.id) AS balance').group('invoices.id')

这篇关于为了通过两个&QUOT总和的查询;的has_many"子表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆