11

假设我们有以下内容:

irb> Post.where(:hidden => true).to_sql
=> "SELECT `posts`.* FROM `posts` WHERE posts.hidden = 1"

我们能以某种方式得到一个倒置的 SQL 查询吗?

我在找什么,应该是这样的:

irb> Post.where(:hidden => true).invert.to_sql
=> "SELECT `posts`.* FROM `posts` WHERE NOT (posts.hidden = 1)"
4

6 回答 6

17

使用不同的语法,是的。例子:

posts = Post.scoped.table # or Arel::Table.new("posts")
posts.where(posts[:hidden].eq(true).not).to_sql
# => SELECT  FROM `posts` WHERE NOT ((`posts`.`hidden` = 1))
于 2011-03-14T19:29:53.290 回答
7

在 rails 4 中not有用于此目的的后缀:

Post.where.not(hidden: true).to_sql
# => SELECT FROM `posts` WHERE `posts`.`hidden` != 1

在 rails 3 中,您可以使用squeel gem。它提供了许多有用的功能。有了它,你可以写:

Post.where{ hidden != true }.to_sql
# => SELECT FROM `posts` WHERE `posts`.`hidden` != 1
于 2013-02-21T09:02:35.917 回答
5

我们可以通过将反向查询传回 ActiveRecord 来进一步了解Zabba 的答案:

table = Post.arel_table
query = table[:hidden].eq(true).not # the inverted query, still ARel
Post.where(query) # plug it back into ActiveRecord

正如您通常期望的那样,这将返回 ActiveRecord 对象。

于 2011-08-12T18:59:28.053 回答
2

invert_where (Rails 7+)

从 Rails 7 开始,有一个新的invert_where方法。

根据文档,它:

允许您反转整个 where 子句,而不是手动应用条件。

class User
  scope :active, -> { where(accepted: true, locked: false) }
end

User.where(accepted: true)
# WHERE `accepted` = 1

User.where(accepted: true).invert_where
# WHERE `accepted` != 1

User.active
# WHERE `accepted` = 1 AND `locked` = 0

User.active.invert_where
# WHERE NOT (`accepted` = 1 AND `locked` = 0)

要小心,因为这会在 invert_where 调用之前反转所有条件。

class User
  scope :active, -> { where(accepted: true, locked: false) }
  scope :inactive, -> { active.invert_where } # Do not attempt it
end

# It also inverts `where(role: 'admin')` unexpectedly.
User.where(role: 'admin').inactive
# WHERE NOT (`role` = 'admin' AND `accepted` = 1 AND `locked` = 0)

资料来源:

于 2021-07-18T23:10:29.437 回答
0

当我在寻找具有“不真实”条件(例如,假或零)的记录时,我会做的是:

Post.where(["(hidden IS NULL) OR (hidden = ?)", false])
于 2012-09-11T06:38:18.323 回答
0

最后我们有了invert_whereRails 7 的方法。

irb> Post.where(:hidden => true).invert_where.to_sql
"SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"hidden\" != 1"

请查看此提交参考以获取更多详细信息。

于 2021-02-17T17:58:59.340 回答