I have a table called Codes on my project.
irb(main):017:0> Code.new
=> #<Code id: nil, company_id: nil, name: nil, employee_uuid: nil, employee_email: nil, redeemed_at: nil, created_at: nil, updated_at: nil>
On my Database i have a total of 97994 Code entries.
irb(main):018:0> Code.all.count
(127.7ms) SELECT COUNT(*) FROM "codes"
=> 97994
So, what i don't understand is the following. So far i tested it with the name attribute.
irb(main):019:0> Code.where(name: "").count
(135.0ms) SELECT COUNT(*) FROM "codes" WHERE "codes"."name" = ? [["name", ""]]
=> 0
irb(main):020:0> Code.where(name: " ").count
(18.3ms) SELECT COUNT(*) FROM "codes" WHERE "codes"."name" = ? [["name", " "]]
=> 0
if the do the oposite Query it should give me the missing objects, on this case my total amount of codes.
irb(main):021:0> Code.where.not(name: "").count
(116.3ms) SELECT COUNT(*) FROM "codes" WHERE ("codes"."name" != ?) [["name", ""]]
=> 94652
irb(main):022:0> Code.where.not(name: " ").count
(19.9ms) SELECT COUNT(*) FROM "codes" WHERE ("codes"."name" != ?) [["name", " "]]
=> 94652
But i get as a result 94652 instead of 97994 (from Code.all.count)
That makes me wonder. I did check what are the left codes:
irb(main):023:0> rest = Code.all - Code.where(name: "") - Code.where.not(name: "")
Code Load (1030.6ms) SELECT "codes".* FROM "codes"
Code Load (16.1ms) SELECT "codes".* FROM "codes" WHERE "codes"."name" = ? [["name", ""]]
Code Load (489.1ms) SELECT "codes".* FROM "codes" WHERE ("codes"."name" != ?) [["name", ""]]
... a huge array was returned
irb(main):024:0> rest.last
=> #<Code id: 86217, company_id: 307, name: nil, employee_uuid: "XXXXXXXXXXXXXX", employee_email: "[email protected]", redeemed_at: "2018-07-09 12:30:29", created_at: "2018-12-11 13:07:57", updated_at: "2018-12-11 13:07:57">
I was curious about this, so i checked one more thing:
irb(main):027:0> rest.last.name == ""
=> false
irb(main):028:0> rest.last.name != ""
=> true
so the rest.last.name is not "" (of course not, name is nil)
but still i get this
irb(main):025:0> Code.where(name: "").include? rest.last
Code Load (108.1ms) SELECT "codes".* FROM "codes" WHERE "codes"."name" = ? [["name", ""]]
=> false
irb(main):026:0> Code.where.not(name: "").include? rest.last
Code Load (365.9ms) SELECT "codes".* FROM "codes" WHERE ("codes"."name" != ?) [["name", ""]]
=> false
I always thought where something, and its negative will always make the total amount, meaning when something happen, and when this something does not happen would give us the always answer. A + !A = 1
Why am i seeing this? i cannot follow this.
Thanks in advance for the help.
Update Question to answer comments:
irb(main):002:0> Code.where(name: [nil, '']).count
(432.2ms) SELECT COUNT(*) FROM "codes" WHERE ("codes"."name" = '' OR "codes"."name" IS NULL)
=> 3342
and this number is exactly
irb(main):003:0> Code.all.count - Code.where.not(name: "").count
(315.2ms) SELECT COUNT(*) FROM "codes"
(332.5ms) SELECT COUNT(*) FROM "codes" WHERE ("codes"."name" != ?) [["name", ""]]
=> 3342
Ok, so far i understand that SQL cannot compare to Nil or not Nil when i test if a string is empty. That means i need to either do the query with array [nil, ''] or think in an other way..
Code.where(name: [nil, '']).count