0

我想使用 squeel 来构建查询,例如:

SELECT * from `table`
WHERE (`field1`, `field2`)
NOT IN (
  (1,"value_a"),
  (2,"value_b"),
  (3,"value_a"),
  ...
)

IN我想知道是否有任何方法可以通过orNOT IN语句将多个字段与数组进行比较。

这样的事情(我知道这个例子不起作用)将是表达我的意思的好方法:

array = [[1,"value_a"], [2,"value_b"], [3, "value_a"]]
Table.where{ (field1 & filed2).not_in array }

这样的事情可能吗?

更新

我知道如何使用 multiple 获得相同的最终结果... & (a != b) & (c != d) & ...,但这不是我所要求的。

4

2 回答 2

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')))
于 2012-12-20T18:21:01.167 回答
0

主要问题是,虽然 Arel(以及 Squeel)支持一些相当复杂的查询,但没有涵盖这种级别的查询复杂性。考虑到这一点,除了使用此功能扩展 Arel 本身之外,恢复到 SQL 并手动构建所需的查询是唯一的解决方案。

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')))

我很想看到更好或更优雅的解决方案,但我还没有找到一个。

于 2012-12-27T14:33:18.720 回答