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
は、0回購入された靴を含め、在庫のある量(この場合は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:長期的には、数十万/数百万の靴がある場合、この問題の最適な解決策は何でしょうか?
前もって感謝します!
============================ 解決策(PostgresSQLではなくMySQLでのみ機能します)道を示してくれた@FrederickCheungに感謝します
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