This is not an answer but comparison of three answers for this question. I have already given my answer. There is confusion w.r.t the working of :joins
and :include
in ActiveRecord.find
. So I spent some time analyzing the SQL log for three solutions.
Approach 1: Get the sales count using 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
Approach 2: Get the products through a 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
Approach 3: Get the products through a 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
Now lets look at the SQL statements generated by these three approaches
SQL statements for Approach 1 - 2 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))
SQL statements for Approach 2 - 2 SQL
SELECT * FROM `products`
SELECT `sales`.* FROM `sales` WHERE (`sales`.product_id IN (1,2))
SQL statements for Approach 3 - N + 1 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)
Best approach for counting product by sales ( with out sales details): Approach 1
Best approach for counting product by sales ( with sales details): Approach 2
Approach 3 has the N+1 problem. So it is out of contention.