这不是一个答案,而是这个问题的三个答案的比较。我已经给出了我的答案。 :joins 和 :include 在 ActiveRecord.find 中的工作存在混淆。所以我花了一些时间分析了三个解决方案的 SQL 日志。
方法一:使用count获取销售计数
#To return the sales count for each product
ps_count_hash = Product.count(:joins => [:sales], :group => "products.id") # sql 1.1
# To print the product id and sales count
ps_count_hash.each do | product_id, sales_count|
p "Product#{product_id} - (#{sales_count})"
end
# To print the product details and sales count
# get all the products associated
Product.find_all_by_id(ps_count_hash.keys).each |product| #sql 1.2
p "Product[id = #{product.id}, name = #{product.name}] - (#{ps_count_hash[product.id]})"
end
方法二:通过join获取产品
Product.find(:all, :joins=>[:sales]).each do |product| #sql 2.1
p "Product[id = #{product.id}, name = #{product.name}] - (#{product.sales.size})" # sql 2.2 - 2.(2+N)
end
方法三:通过include获取产品
Product.find(:all, :include=>[:sales]).each do |product| #sql 3.1 and 3.2
p "Product[id = #{product.id}, name = #{product.name}] - (#{product.sales.size})"
end
现在让我们看看这三种方法生成的 SQL 语句
方法 1 - 2 SQL 的 SQL 语句
SELECT count(*) AS count_all, products.id AS products_id FROM `products` INNER JOIN `sales` ON sales.product_id = products.id GROUP BY products.id
SELECT `products`.* FROM `products` WHERE (`products`.`id` IN (1,2))
方法 2 - 2 SQL 的 SQL 语句
SELECT * FROM `products`
SELECT `sales`.* FROM `sales` WHERE (`sales`.product_id IN (1,2))
方法 3 - N + 1 SQL 的 SQL 语句
SELECT `products`.* FROM `products` INNER JOIN `sales` ON sales.product_id = products.id
SELECT * FROM `sales` WHERE (`sales`.product_id = 1)
SELECT * FROM `sales` WHERE (`sales`.product_id = 2)
按销售额计算产品的最佳方法(不含销售详情):方法 1
按销售额计算产品的最佳方法(包含销售详情):方法 2
方法 3 存在 N+1 问题。所以它是没有争议的。