2013-04-02 88 views
1

我遇到的情況,我有SQL的地方加入查詢鏈,然後在另外一些時候,我需要追加哪些需要同樣的加入條件,但我不知道這一點是否該連接已經存在於範圍內。例如:避免重複在Rails的ActiveRecord的查詢連接

@foo = Foo.joins("INNER JOIN foos_bars ON foos_bars.foo_id = foos.id") 
.... 
@foo.joins(:bars).where(bars: { id: 1 }) 

這將產生有關重複表/別名的SQL錯誤。

我寫的SQL之所以在一審手動加入是改善經典的軌道AREL連接將產品兩個內連接凡在我來說,我只需要一個效率。

有沒有解決這個推薦的方法是什麼?例如,查看當前在範圍內的聯接的一些方法。

迴應評論:

隨着has_and_belongs_to_many關係的Rails產生兩個INNER JOINS這樣的:

SELECT "journals".* FROM "journals" 
INNER JOIN "categories_journals" 
    ON "categories_journals"."journal_id" = "journals"."id" 
INNER JOIN "categories" 
    ON "categories"."id" = "categories_journals"."category_id" 
WHERE "categories"."id" = 1 

而我相信我能做到這一點,而不是:

SELECT "journals".* FROM "journals" 
INNER JOIN "categories_journals" 
    ON "categories_journals"."journal_id" = "journals"."id" 
WHERE "categories_journals"."category_id" = 1 

糾正我,如果我錯了。

+0

你做了什麼樣的分析,證明做加入的你更「有效」的方式實際上是更好?其實,是什麼讓你覺得你只需要一個連接?即使您反覆嘗試反覆加入同一張表,AREL也不會建立不必要的連接。 – messick

+0

我更新了我的問題,因爲評論@messick太長了。 –

+0

我建議讓AREL做它的事情。您的解決方案正在擊敗ORM的一個主要優點,它是'自動'具有映射到數據庫表的對象的。如果加入到Categories表格真的是一個性能問題,我會回頭想想Rails是否真的是你想要使用的東西。 – messick

回答

1

的解決方案是普遍使用的字符串連接。不知道我的Rails實際上是uniq的字符串連接 - 所以只要他們是字符串相同這個問題不會發生。

This article把我的氣味,筆者表現出完全一樣的問題,因爲我和補丁Rails的,它看起來像補丁是很久以前實現。我不認爲這是完美的。應該有一種方法來處理散列參數聯接和字符串聯接,並且在重疊時不會彈出。可能會看到,如果我可以修補的..

編輯:

我做了幾個基準測試,看看是否我真的很擔心沒什麼與否(加盟的兩種方法之間):

1.9.3p194 :008 > time = Benchmark.realtime { 1000.times { a = Incident.joins("INNER JOIN categories_incidents ON categories_incidents.incident_id = incidents.id").where("categories_incidents.category_id = 1") } } 
=> 0.042458 
1.9.3p194 :009 > time = Benchmark.realtime { 1000.times { a = Incident.joins(:categories).where(categories: { id: 1 }) } } 
=> 0.152703 

我不是一個普通的基準測試人員,所以我的基準測試可能並不完美,但在我看來,好像我的更高效的方法確實能夠在大型查詢或大量查詢上實現真實世界的性能改進。

加入我做的方式的缺點是,如果Category不存在但仍記錄在連接表中,那麼可能會導致一些問題,否則可以通過更徹底的連接來避免。