2017-01-09 9 views
0

Ruby on Railsプロジェクト4.0では、私はPaymentsモデルhas_manyTransactionsモデルを持っています。特定の条件に一致するモデルが関連付けられているモデルの合計属性

私は今、次のデータ

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 

をお持ちの場合は

> 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 
を次のように、私は、特定のタイプのトランザクションを持っている Paymentsから数値属性 paid_amount、の合計を計算しています

しかし、これは何千ものレコードで十分に速く動作しないので、私は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 

私は必要な数をどのように計算すればよいですか?

答えて

1

あなたの最初のクエリ:Transaction.where(type: 'cash').pluck(:payment_id)はクエリがあるので

Payment.where(id: Transaction.where(type: 'cash').pluck(:payment_id)).sum(:paid_amount) 

は、部分的に遅いです配列を返し、その配列を送信するbaデータベース内のSQLにIN (big_list_of_integers)を追加します。

select sum(payments.paid_amount) 
from payments 
where payments.id in (
    select payment_id 
    from transactions 
    where transactions.type = ... 
) 

がデータベースに送信されている:よう

Payment.where(id: Transaction.where(type: 'cash').select(:payment_id)).sum(:paid_amount) 

その一つのクエリになります:若干の修正が単にpluckselectに切り替え、代わりにサブクエリを使用します。これは、大きなリストではかなり速くなるはずです。

-1

whereで使用joinsは、あなたがしたいことだけ取引を戻す

joins documentation

Payment.joins(:transactions).where(transactions: {type:'cash'}).sum(:paid_amount)

関連する問題