我正在使用postgresql。
我有一个名为custom_field_answers的表。数据看起来像这样。
Id | product_id | value | number_value |
4 | 2 | | 117 |
3 | 1 | | 107 |
2 | 1 | bangle | |
1 | 2 | necklace | |
我想找到所有产品,其text_value为'bangle',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。
答案 0 :(得分: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 Arel Wrapper好,但对于复杂的查询,如果你不想在你的代码中放弃原始SQL,这是唯一的方法。
这有帮助吗?
答案 1 :(得分:-1)
Select * from products where product_id
IN
(Select product_id from custom_answers
where
text_value = 'bangle'
AND number_value<50)