2011-11-01 63 views
0

產品在限定的時間內在網站上銷售。我需要在Rails ActiveRecord中重寫這個SQL查詢嗎?

每筆銷售開始於DATE,結束於DATE,幷包含至少一個產品。

每個產品都與它所屬的銷售ID#相關聯。

有時銷售內沒有產品的時間很短,因爲經理創建了銷售,但尚未完成與銷售的關聯產品,因此我必須在顯示產品時過濾掉沒有產品的銷售即將到來的銷售清單,否則會混淆用戶。

在我Sale模式,我想出了這個,因爲我不是那熟悉的ActiveRecord:

def upcoming_sales 
    find_by_sql(["SELECT DISTINCT sales.* from sales, products WHERE products.sale_id = sales.id AND sales.start_at > ? AND sales.start_at < ? ORDER BY sales.start_at ASC", Time.now, (Time.now + END_AT)]) 
end 

我相信上面的SQL是標準ANSI SQL應該運行在幾乎任何數據庫服務器,但是可以用ActiveRecord來完成嗎?

除了對非SQL用戶友好以外,ActiveRecord還有什麼好處?

哪種方式更好,性能明智?

回答

2

原始SQL很難維護。性能明智的原始sql更好,但考慮以下好處ActiveRecord。你會得到一個很好的查詢語法,考慮到其他人可能需要修改你的代碼,這個語法更具可讀性。另外,ActiveRecord可以讓您對數據庫引擎不可知的程度達到原始sql無法實現的程度。

但是,如果你認爲性能是你唯一的瓶頸,那麼ActiveRecord落後。我會說,做一個小小的研究。上面的查詢是一個連接查詢,絕對原始的SQL會給你帶來顯着的性能好處。很多其他的事情可以大大提高查詢的性能,如正確的indexing,caching,eager loading(當需要時,因爲有時急切的加載實際上會導致查詢變慢)等等。在你溝居之前ActiveRecord確定它確實是瓶頸。

2

當然你也可以編寫自定義的SQL,但是當AR工作得很好很不可取的(你會得到均勻透明的代碼,DB-獨立,...):

def upcoming_sales 
    select('DISTINCT sales.*'). 
    joins(:products). 
    where(["sales.start_at > ? AND sales.start_at < ?", Time.now, Time.now + END_AT]). 
    order("sales.start_at ASC") 
end