2011-11-23 3 views
0

J'utilise postgresql.Comment rejoindre la même table plusieurs fois

J'ai une table appelée custom_field_answers. Les données ressemblent à ceci.

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

Je veux trouver tous les produits qui TEXT_VALUE comme 'Bangle' et NUMBER_VALUE moins de 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 

J'ai essayé de produire cette sql avec le code suivant.

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 

Ce produit suivant 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) 

Comme vous pouvez le voir ce sql ne ressemble pas à l'sql désiré (mentionné en haut).

J'ai essayé de déplacer le joint coder un peu comme celui-ci

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

Toujours pas de chance. Tout le monde sait comment forcer une nouvelle jointure pour chaque relation. J'utilise Rails 3.1.1.

Répondre

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

Votre meilleur pari pour les requêtes « standards non » comme ceux-ci serait d'aller vers le bas à Arel.

Quelque chose comme cela devrait fonctionner:

# 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 

Pas aussi bien que les rails Arel Wrapper, mais pour les requêtes complexes, il est la seule façon si vous ne voulez pas déposer à SQL brute dans votre code.

Est-ce que cela aide?

Questions connexes