Это не ответ, а сравнение трех ответов на этот вопрос. Я уже дал свой ответ. Существует путаница с работой :joins
и :include
в ActiveRecord.find
. Поэтому я потратил некоторое время на анализ журнала SQL для трех решений.
Подход 1: Получить счет продаж, используя 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
Подход 2: Получить продукты через 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
Подход 3: Получить продукты через 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, сгенерированные этими тремя подходами
SQL-операторы для подхода 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-операторы для подхода 2 - 2 SQL
SELECT * FROM `products`
SELECT `sales`.* FROM `sales` WHERE (`sales`.product_id IN (1,2))
SQL-операторы для подхода 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)
Лучший подход для подсчета продукта по продажам (без данных о продажах): Подход 1
Лучший подход для подсчета продукта по продажам (с подробностями продаж): Подход 2
Подход 3 имеет проблему N + 1. Так что это вне раздора.