我有一个关于在 ActiveRecord 中形成查询的问题,但也为不熟悉 ActiveRecord 的人提供了 SQL。
我有以下模型类:
class Shoe < ActiveRecord::Base
has_many :purchases
def self.available_shoes
#show all shoes that have been purchased less than num_in_stock
num_in_stock = 3
Shoe.includes(:purchases)
.group("purchases.shoe_id")
.having("COUNT(purchases.shoe_id) < ?", num_in_stock)
end
def self.available_shoes_for_user(user)
#show all available_shoes that a user hasn’t already purchased
Shoe.available_shoes.where("purchases.user_id != ?", user.id)
end
end
该方法Shoe.available_shoes
按预期工作,因为它将返回所有购买次数少于库存数量的鞋子(在本例中为 3),包括购买次数为零的鞋子。
当我打电话时出现问题Shoe.available_shoes_for_user(user)
,它会显示所有已购买的鞋子,但不显示购买量为零的可用鞋子。
我提取了下面的原始 SQL:
#Shoe.available_shoes
SELECT shoes.*, purchases.* FROM shoes LEFT OUTER JOIN purchases ON purchases.shoe_id = shoes.id GROUP BY shoe_id HAVING COUNT(purchases.shoe_id) < 3
#Shoe.available_shoes_for_user(User.find(5))
SELECT shoes.*, purchases.* FROM shoes LEFT OUTER JOIN purchases ON purchases.shoe_id = shoes.id WHERE (purchases.user_id != 5) GROUP BY shoe_id HAVING COUNT(purchases.shoe_id) < 3
问题 1:我怎样才能Shoe.available_shoes_for_user(user)
按预期工作(即显示所有购买次数少于 3 次(包括 0 次)且客户尚未购买的鞋子?
问题2:从长远来看,当有几十万/几百万只鞋子时,这个问题的最佳解决方案是什么?
提前致谢!
============================ 一个解决方案(仅适用于 MySQL 而不是 PostgresSQL)感谢@Frederick Cheung 指路
class Shoe < ActiveRecord::Base
has_many :purchases
def self.available_shoes
#show all shoes that have been purchased less than num_in_stock
num_in_stock = 3
Shoe.includes(:purchases)
.group("purchases.shoe_id")
.having("COUNT(purchases.shoe_id) < ?", num_in_stock)
end
def self.available_shoes_for_user(user)
#show all available_shoes that a user hasn’t already purchased
Shoe.available_shoes
.joins("LEFT OUTER JOIN purchases purchased_by_user ON purchased_by_user.shoe_id = shoes.id AND purchased_by_user.user_id = '#{user.id}'")
.where("purchased_by_user.id IS NULL")
end
end