我想使用squeel来构建如下的查询:
SELECT * from `table`
WHERE (`field1`, `field2`)
NOT IN (
(1,"value_a"),
(2,"value_b"),
(3,"value_a"),
...
)
我想知道是否有任何方法可以通过IN
或NOT IN
语句将多个字段与数组进行比较。
这样的事情(我知道这个例子不起作用)是表达我的意思的好方法:
array = [[1,"value_a"], [2,"value_b"], [3, "value_a"]]
Table.where{ (field1 & filed2).not_in array }
这样的事情是否可能?
我知道如何使用多个... & (a != b) & (c != d) & ...
获得相同的最终结果,但这不是我所要求的。
答案 0 :(得分:1)
也许这样?
Product.where{
(title != 'foo') & (description != 'bar') |
(title != 'baz') & (description != 'xyz')
}
如果您已经有一个要排除值的数组,您可以创建一个这样的范围:
scope :without_title_and_description, lambda{|array|
where{array.map{|c1,c2| (title != c1) & (description != c2)}.inject(:|)}
}
并使用它:
array = [[1,"value_a"], [2,"value_b"], [3, "value_a"]]
Product.without_title_and_description(array)
产地:
Product Load (1.0ms) SELECT "products".* FROM "products" WHERE (((("products"
."title" != 1 AND "products"."description" != 'value_a') OR ("products"."title"
!= 2 AND "products"."description" != 'value_b')) OR ("products"."title" != 3 AND
"products"."description" != 'value_a')))
答案 1 :(得分:0)
主要问题是,虽然Arel(以及Squeel)支持一些相当复杂的查询,但不包括这种级别的查询复杂性。考虑到这一点,恢复到SQL并手动构建所需的查询是唯一的解决方案,而不是使用此功能扩展Arel本身。
existing_compound_ids = [[1,"value_a"],[2,"value_b"],[3, "value_a"]]
compound_collection = existing_compound_ids.inject([]) do |aftermath, member|
aftermath << "('#{ member[0] }','#{ member[1] }')"
end.join(",")
Table.where("(`tables`.`field1`, `tables`.field2) NOT IN (#{compound_collection})")
将构造以下SQL:
SELECT `tables`.* from `tables` WHERE ((field1, field2)
NOT IN (('1','value_a'),('2','value_b'),('3','value_a')))
我希望看到更好,更优雅的解决方案,但我还没找到。