所以我试图获得两个独立的价值观。已完成所有付款的发票和已支付部分付款的发票。 这是一个rails应用程序
Invoices has_many :payments
支付付款:真实或付款:虚假。 因此,在我的第一次通话中,我希望获取已完成所有付款的那些发票的发票ID。我试过了:
SELECT DISTINCT (invoices.id) FROM "invoices" join payments on payments.invoice_id = invoices.id WHERE "invoices"."payer_id" = 1 AND (payments.paid = ALL(array[true]))
不幸的是,即使支付了3分中的2分,这也会为发票返回一行:true
接下来的电话是获得一些付款的发票:真实,有些付款:假。为此,我尝试过:
SELECT DISTINCT (invoices.id) FROM "invoices" join payments on payments.invoice_id = invoices.id WHERE "invoices"."payer_id" = 1 AND (payments.paid = SOME(array[true]) AND payments.paid = SOME(array[false]))
但是,即使该发票中的某些付款已付款而其他付款尚未付款,这也不会返回一行。
我是否正确使用了ALL和SOME?或者还有另一种方式来打这个电话吗?似乎是一个相当简单的电话,所以我确信有一些方法可以做到这一点。谢谢你的帮助!
答案 0 :(得分:1)
=ALL (array[...])
表示等于数组的所有元素,当数组只有一个元素时,它等同于简单的相等测试。
因此payments.paid = ALL(array[true])
相当于payments.paid = true
。
通过类似的逻辑,payments.paid = SOME(array[false])
相当于payments.paid = false
。
此查询似乎不需要或不需要数组和ALL / SOME。它可以这样表达:
"查找没有付款的相应付款的发票= false"
select distinct I.id
from invoices I
where payer_id=1
and not exists (select 1 FROM payments P WHERE P.invoice_id=I.id AND P.paid=false);
表达它的另一种方式:
"查找付款计数等于p.paid = true的付款计数的发票(意味着全部付款)"
select I.id
from invoices I join payments P on (I.id=P.invoice_id)
group by I.id
having sum(P.paid::int)=count(*);
当p.paid为真时, p.paid::int
求值为1,当p.paid为假时,
having
求值为0
对于其他查询,您可以使用having sum(P.paid::int)<count(*)
子句。
例如,{{1}}将仅保留付款金额小于此发票付款次数的发票,这意味着它们并未完全支付。