我在以下型号上努力使用N + 1:
class Transaction < ActiveRecord::Base
attr_accessible :amount
belongs_to :user
scope :retail, where("wholesale = 0")
scope :wholesale, where("wholesale = 1")
end
class User < ActiveRecord::Base
attr_accessible :name, :email
has_many :transactions
end
我需要保留零售/批发的范围(它们可以是方法),因为它们被广泛使用。但是,我很难将它们纳入一份报告,该报告按用户的基础对零售和批发交易进行总结。
我能得到的最接近的是两个查询:
Transaction.retail.group(:user_id).sum(:amount)
Transaction.wholesale.group(:user_id).sum(:amount)
返回两个有序哈希值。该报告需要用户/电子邮件,因此在合并两个哈希值后我将回到N + 1问题。
我尝试过选择:
Transaction
.joins(:user)
.select("users.name, users.email, sum(amount) as wholesale_amount")
.where(wholesale: true)
但它返回[#<Transaction >]
这是奇怪的。我无法访问返回数组中的任何属性或使用它。
最好,我想用一个查询来做这件事。以下是直接返回我正在寻找的SQL:
SELECT
u.name,
u.email,
SUM(CASE WHEN wholesale = 1 THEN amount ELSE 0 END) AS wholesale_amount,
SUM(CASE WHEN wholesale = 0 THEN amount ELSE 0 END) AS retail_amount
FROM transactions r
LEFT JOIN users u ON u.id = r.user_id
GROUP BY user_id
ORDER BY u.name;
...但它复制了条件条件中的范围逻辑。
我觉得有一个明显的答案我错过了。
编辑: 这就是我现在最终要做的事情。
Transaction
.joins(:user)
.select("users.name")
.select("users.email")
.select("SUM(CASE WHEN wholesale = 0 THEN amount ELSE 0 END) AS retail_available")
.select("SUM(CASE WHEN wholesale = 1 THEN amount ELSE 0 END) AS wholesale_available")
.select("SUM(CASE WHEN wholesale = 1 THEN amount ELSE 0 END) + SUM(CASE WHEN wholesale = 0 THEN amount ELSE 0 END) AS total_available")
.group("users.id")
.having("SUM(CASE WHEN wholesale = 1 THEN amount ELSE 0 END) + SUM(CASE WHEN wholesale = 0 THEN amount ELSE 0 END) > 0")
.order("users.name")
我可能会做的是避免重复,将wholesale = 0
字符串放在方法中,并将它们用于范围条件和此方法。我不是这种方法的粉丝,也许是尖叫的东西可以让它更容易,我不知道。它虽然有效。
如果有人对此采用类似红宝石的方法,我会保持开放状态。