在Ruby on Rails项目4.0中,我有Payments
模型,has_many
Transactions
模型。
如果我有以下数据
SELECT * FROM payments;
id | paid_amount
---+--------------
1 | 200
2 | 300
3 | 100
4 | 400
5 | 100
6 | 600
7 | 100
8 | 100
9 | 800
SELECT * FROM transactions;
id | payment_id | type
---+-------------+------
1 | 2 | cash
2 | 3 | credit
3 | 1 | credit
4 | 4 | cash
5 | 1 | cash
6 | 6 | credit
7 | 1 | cash
8 | 1 | credit
9 | 8 | cash
现在,我正在计算来自paid_amount
的数字属性Payments
的总和,该属性具有特定类型的交易,如下所示
> Payment.where(id: Transaction.where(type: 'cash').pluck(:payment_id)).sum(:paid_amount)
> 1000
> # The sum of paid_amount from payments with ids 1, 2, 4 and 8
但这对于成千上万的记录来说效率不够快,所以我试图用includes
来完成这个,但没有任何运气。
> Payment.includes(:transactions).where("transactions.type = 'cash'").sum(:paid_amount)
> 1200
> # paid_amount of payment with id 1 is considered two times because of transactions with id 5 and 7
有关如何计算我需要的数字的任何想法?
答案 0 :(得分:1)
您的第一个查询:
Payment.where(id: Transaction.where(type: 'cash').pluck(:payment_id)).sum(:paid_amount)
部分缓慢,部分原因是Transaction.where(type: 'cash').pluck(:payment_id)
是一个返回数组的查询,然后您将该数组发送回SQL中的IN (big_list_of_integers)
数据库。稍加修改将使用子查询,只需将pluck
切换为select
:
Payment.where(id: Transaction.where(type: 'cash').select(:payment_id)).sum(:paid_amount)
将导致一个查询,如:
select sum(payments.paid_amount)
from payments
where payments.id in (
select payment_id
from transactions
where transactions.type = ...
)
被发送到数据库。对于大型列表,这应该会快得多。
答案 1 :(得分:-1)
将joins
与where
一起使用,只返回您想要的交易
Payment.joins(:transactions).where(transactions: {type:'cash'}).sum(:paid_amount)