gpt4 book ai didi

sql - 为什么这个双重否定查询与肯定查询不同?

转载 作者:行者123 更新时间:2023-11-29 11:54:45 25 4
gpt4 key购买 nike

当我进行两个应该选择同一组人的查询时,它们有不同的结果。逻辑是一样的,只是数字不同。

这是我的模型:Person 类,年龄为:整数 name:string pet:string

class Person < ApplicationRecord
PET_TYPES = ['dog', 'cat', 'bird', 'fish']
validates :pet, inclusion: { in: PET_TYPES }, allow_nil: true
validates :age, numericality: { greater_than: 0 }
end

我已经在我的种子文件中用 21 岁以下或 21 岁以上拥有每种宠物(包括零)的人填充了数据库:

Person.all.destroy_all
Person::PET_TYPES.each do |pet|
10.times do |n|
Person.create!(name: "Person-young-#{pet}-#{n}", pet: pet, age: (1..20).to_a.sample)
end
10.times do |n|
Person.create!(name: "Person-old-#{pet}-#{n}", pet: pet, age: (21..80).to_a.sample)
end
end
10.times do |n|
Person.create!(name: "Person-young-no-pet-#{n}", pet: nil, age: (1..20).to_a.sample)
end
10.times do |n|
Person.create!(name: "Person-old-no-pet-#{n}", pet: nil, age: (21..80).to_a.sample)
end

我执行了以下两个查询,它们应该选择同一组人。但我得到不同的数字。

Person.count
#>> (1.0ms) SELECT COUNT(*) FROM "people"
#=> 100
Person.where.not(id: Person.where.not('age > ? AND pet = ?', 21, 'dog')).count
#>> (1.7ms) SELECT COUNT(*) FROM "people" WHERE "people"."id" NOT IN (SELECT "people"."id" FROM "people" WHERE NOT (age > 21 AND pet = 'dog'))
#=> 20
Person.where('age > ? AND pet = ?', 21, 'dog').count
#>> (1.0ms) SELECT COUNT(*) FROM "people" WHERE (age > 21 AND pet = 'dog')
#=> 10

这两个语句不应该返回相同的数字吗?

最佳答案

在 SQL 中,null 不等于 (=) 任何东西——甚至不等于另一个 null。此外,这是 Three-valued logic 的常见示例.当您将 null 与其他任何内容进行比较时,它既不是真也不是假;它是 UNKNOWN

基本的“问题”是(如更深入的讨论 here )where.not(x: true)WHERE x != true;它不是 WHERE x == true 的否定形式。

让我们将您的问题分解为一个最小、完整、可验证的示例:

Person.count
(1.2ms) SELECT COUNT(*) FROM "people"
=> 100
Person.where(pet: 'dog').count
(1.0ms) SELECT COUNT(*) FROM "people" WHERE "people"."pet" = 'dog'
=> 20
Person.where.not(pet: 'dog').count
(1.4ms) SELECT COUNT(*) FROM "people" WHERE "people"."pet" != 'dog'
=> 60
Person.where.not(pet: 'dog').pluck(:pet).uniq
=> ["cat", "bird", "fish"]

如您所见,两个结果中都缺少拥有 null 宠物的人。


总而言之,由于三值逻辑,您尝试双重否定查询实际上会导致不同的结果集。

Person.where.not('age > ? AND pet = ?', 21, 'dog') 包括除了有狗的老人之外的所有人 没有宠物的老人。

关于sql - 为什么这个双重否定查询与肯定查询不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55407736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com