【问题标题】:Rails Active Record Queries - Not Equal and Blank/Empty StringsRails Active Record 查询 - 不等于和空白/空字符串
【发布时间】:2014-05-04 07:30:11
【问题描述】:

我有一个活动记录查询,其中包含一个字符串的 Not Equal 子句。例如:

 Post.where.not(title: "Rails 4")

 Post.where("title != ?", "Rails 4")

但是,如果标题为空或空白,则不会包含在结果中。 我如何才能同时包含标题为空白或空的记录?

例如:

帖子

id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"

实际结果:

Post.where.not(title: "Rails 4") #=> [3]

期望的结果:

Post.where.not(title: "Rails 4") #=> [2, 3]

【问题讨论】:

  • 您使用的是什么数据库?在 postgres 中,where.not(title: 'Rails 4') 如果 #2 标题是空字符串(如您所指),将返回所需的行(#2 和 #3)。如果 #2 的标题为 null,则结果将被跳过,因为任何与 null 的比较总是错误的。如果这是您的意思,请更新问题以指定空值。

标签: sql ruby-on-rails activerecord ruby-on-rails-4


【解决方案1】:

试试下面的查询

Post.where("title != ? OR title = ?", "Rails 4",'')

【讨论】:

  • 这只会返回标题为空白的结果
  • @Babar 你检查了吗?
  • 问题是我没有在我的家用电脑上设置我的系统。所以我必须相信你的话....但我不知道它会如何翻译以获取表中除了“RAILS 4”之外的所有内容
  • 我认为将 AND 更改为 OR 应该是这样的方式
  • NULL 在不一样的''
【解决方案2】:

您可以在此处手动键入 SQL 并可能创建一个数据库依赖项,或者使用 ActiveRecord 与 Arel 结合使用,可读性稍差,但效果很好:

table = Post.arel_table

Post.where(table[:title].not_eq('Rails 4').or(table[:title].eq('')))

【讨论】:

    【解决方案3】:

    *注意 我假设您使用的是 postgres 之类的数据库,并且您遇到的问题是空值,而不是空字符串值。如果没有返回空字符串值,那么你有一个完全不同的问题

    where.not(title: 'Rails 4') 没有返回您所期望的原因是您在字符串字段中有空值,并且与 null 的任何比较都将为空,这是错误的。

    帖子

    id => 1, title => "Rails 4"
    id => 2, title => ""
    id => 3, title => "Rails 3"
    id => 4, title => NULL
    

    为了在结果中包含 Post #4,您需要显式包含空值。一种方法是使用IS NULL

    # Original - excludes rows with null title
    Post.where.not(title: "Rails 4") #=> [2,3]
    # SELECT posts.* FROM posts WHERE posts.title != 'Rails 4' 
    
    # Option #1 - explicitly include null
    Post.where.not(title: "Rails 4").or(Post.where(email: nil)) #=> [2,3,4]
    # SELECT posts.* FROM posts WHERE (posts.title != 'Rails 4' OR posts.title IS NULL)
    
    # Option #2 - replace null values with empty string
    POST.where.not("coalesce(posts.title, '') = ?", 'Rails 4')
    # SELECT posts.* FROM posts WHERE NOT (coalesce(posts.title, '') = 'Rails 4')
    

    第三种解决方案是在您的字符串字段中完全禁止空值(使用NOT NULL 约束)。在字符串字段中允许空值可能会产生其他意想不到的副作用 - 例如,如果您通过“电子邮件”对帖子进行排序,那么带有空电子邮件的帖子将显示在与带有空字符串电子邮件的帖子不同的位置,但是对用户来说,它看起来很混乱。

    【讨论】:

      【解决方案4】:

      Pavans 的答案是正确的,就用这个

      Post.where("title != ? OR title = ?", "Rails 4",'')
      

      【讨论】:

        【解决方案5】:

        我知道这已经 7 年了,但它仍然出现在 Google 上。更好的解决方案是使用拒绝而不是 where.not

        Post.all.reject{|x| x.title == "Rails 4"}
        

        【讨论】:

        • 这会将数据库中的每个对象加载到内存中,然后遍历每个对象。对于大型表,这可能会使服务器崩溃。请谨慎使用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多