[英]Rails Active Record Queries - Not Equal and Blank/Empty Strings
我有一個活動記錄查詢,其中包含一個字符串的 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]
試試下面的查詢
Post.where("title != ? OR title = ?", "Rails 4",'')
*注意我假設您正在使用像 postgres 這樣的數據庫,並且您遇到的問題是 null 值,而不是空字符串值。 如果沒有返回空字符串值,那么你有一個完全不同的問題
where.not(title: 'Rails 4')
沒有返回您期望的結果的原因是您在字符串字段中有 null 個值,並且與 null 的任何比較都將是 null,這是錯誤的。
帖子
id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"
id => 4, title => NULL
為了在結果中包含 Post #4,您需要明確包含 null 個值。 一種方法是使用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')
第三種解決方案是完全禁止字符串字段中的 null 值(具有NOT NULL
約束)。 在字符串字段中允許 null 值可能會產生其他意想不到的副作用 - 例如,如果您通過“電子郵件”訂購帖子,那么帶有 null email 的帖子將顯示在與帶有空字符串 email 的帖子不同的位置,但是對用戶來說,它看起來很混亂。
您可以在此處手動鍵入SQL並可能創建數據庫依賴項,或者將ActiveRecord與Arel結合使用,后者可讀性較差,但運行良好:
table = Post.arel_table
Post.where(table[:title].not_eq('Rails 4').or(table[:title].eq('')))
Pavans答案是正確的,只需使用它
Post.where("title != ? OR title = ?", "Rails 4",'')
我意識到這已經 7 年了,但它仍然出現在谷歌上。 更好的解決方案是使用 reject 而不是 where.not
Post.all.reject{|x| x.title == "Rails 4"}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.