2011-11-23 105 views
0

我正在使用postgresql。如何多次加入同一個表

我有一個名爲custom_field_answers的表。數據看起來像這樣。

Id | product_id | value  | number_value | 
4 | 2   |   | 117   | 
3 | 1   |   | 107   | 
2 | 1   | bangle  |    | 
1 | 2   | necklace |    | 

我想找到所有已TEXT_VALUE爲「手鐲」和NUMBER_VALUE小於50

SELECT p.* 
FROM "products" AS p 
INNER JOIN "custom_field_answers" AS a1 ON p."id" = a1."product_id" 
INNER JOIN "custom_field_answers" AS a2 ON p."id" = a1."product_id" 
WHERE a1."value" = 'bangle' AND a2."number_value" < 50 

我試圖產生SQL與下面的代碼的產品。

conditions = <conditions from arel> 
relation = self.scoped 
conditions.each do |condition| 
    relation = relation.merge(where(condition)) 
end 
joins(:custom_field_answers).merge(relation) 
relation.to_a 

這產生以下SQL

SELECT "products".* FROM "products" INNER JOIN "custom_field_answers" 
ON "custom_field_answers"."product_id" = "products"."id" 
WHERE ("custom_field_answers"."value" ILIKE 'bangle') 
AND ("custom_field_answers"."number_value" < 50) 

正如你可以看到這個SQL不類似於期望的SQL(在頂部提到的)。

我試圖移動加入了代碼有點像這樣

relation = self.scoped 
conditions.each do |condition| 
    relation = relation.merge(where(condition).joins(:custom_field_answers)) 
end 
relation.to_a 

仍然沒有運氣。

任何人都知道如何強制每個關係的新連接。我正在使用Rails 3.1.1。

回答

-1
Select * from products where product_id 
IN 
(Select product_id from custom_answers 
    where 
    text_value = 'bangle' 
    AND number_value<50) 
6

對於'非標準'查詢,最好的辦法就是直接去找Arel

像這樣的東西應該工作:

# in your model 
p = Arel::Table.new(:products, :as => 'p') 
a1 = Arel::Table.new(:custom_field_answers, :as => 'a1') 
a2 = Arel::Table.new(:custom_field_answers, :as => 'a2') 

relation = p. 
    project(Arel.sql('*')). 
    join(a1).on(p[:id].eq(a1[:product_id])). 
    join(a2).on(p[:id].eq(a2[:product_id])) 

relation = relation.where(a1[:value].eq('bangle')).where(a2[:number_value].lt(50)) 

relation.to_sql #should return the SQL you're after 

不一樣好了Rails阿雷爾包裝,但對於複雜的查詢,如果你做你的代碼不想下降到原始的SQL是唯一的方法。

這有幫助嗎?