Rails Active Records - where, where-not and nil

Today my coworker pointed out that confusing behavior of where.not query dealing with nil. We need extra care when filtering SQL queries with nil. I'll put it together for future reference.

all records

User.all.count
#=> 1509

nil | non-nil

Records that have nil comment id

# The "nil" group
User.where(comment_id: nil).count
#=> 191

Records that have non-nil comment id

# The "non-nil" group
User.where.not(comment_id: nil).count
#=> 1318

matching id | the rest

Records that has comment_id 839

User.where(comment_id: [839]).count
#=> 8

Records that does not have comment_id 839

User.where.not(comment_id: [839]).or(User.where(comment_id: nil)).count
#=> 1501

WARNING: The following does not do the job for this type of grouping.

# Bad example
User.where.not(comment_id: [839]).where.not(comment_id: nil).count
User.where.not(comment_id: [nil, 839]).count

matching id | not matching non-nil | nil id

Records that has comment_id 839

# find records that has comment_id 839
User.where(comment_id: [839]).count
#=> 8

Records that do not have comment_id 839 AND that do not have nil comment_id

User.where.not(comment_id: [839]).where.not(comment_id: nil).count
#=> 1310

Records that have nil comment id

User.where(comment_id: nil).count
#=> 191

Resources