我有一個關於在ActiveRecord中形成查詢的問題,但也爲那些不熟悉ActiveRecord的人提供了SQL。如何調整ActiveRecord(或直接SQL)查詢以在包含WHERE子句的JOIN中包含零計數記錄
我有以下模型類:
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
如預期的,因爲它會返回已比現貨供應量購買更少的時間所有的鞋(在這種情況下3)Shoe.available_shoes
工作方法,包括購買了零次的鞋子。
問題出在我打電話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倍以上(包括零次),其客戶端尚未購買
問題2:從長遠來看,這將是解決這一問題的最佳解決方案時,有幾十萬/百萬雙鞋
?提前致謝!
============================ 一個解決方案:(僅在MySQL工作不PostgreSQL的) 由於@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
我假設你使用MySQL?你的代碼工作*(只對'.group'進行小的語法修改)*在PostgreSQL中很好。 – deefour 2012-07-10 04:22:16
似乎沒有問題,因爲 'Shoe.includes(:purchases).group(「purchases.shoe_id」)。having(「COUNT(purchases.shoe_id)<?」,2)' 也顯示有零購買,因爲這會執行左外連接。 – prasvin 2012-07-10 05:23:37
@Deefour是的,與MySQL合作。 – madhermit 2012-07-10 16:43:55