2017-01-09 1 views
0

Ruby on Rails 프로젝트 4.0에서 has_manyTransactions 모델 인 Payments 모델이 있습니다.특정 조건과 일치하는 모델이있는 모델의 합계 속성

나는 지금 다음 데이터

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 ck를 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)

관련 문제