mysql - 如果 NULL 值在列中可用,则查询条件
问题描述
我不明白两个查询之间的区别,请参阅图片。注意最后一个条件。mysql版本是5.7有什么神奇之处?
select distinct(pc) as aggregate
from `installers`
where
`success` =1
and
date(created_at) >= '2018-08-15'
and
date(created_at) <= '2018-08-21'
and
(free=0 or free is null)
(免费为空或免费=0)
select distinct(pc) as aggregate
from `installers`
where
`success` =1
and
date(created_at) >= '2018-08-15'
and
date(created_at) <= '2018-08-21'
and
free!=1
免费!=1
表结构
CREATE TABLE `installers` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`driver_id` BIGINT(20) UNSIGNED NOT NULL,
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NULL DEFAULT NULL,
`success` TINYINT(4) NULL DEFAULT NULL,
`version` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`pc` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci',
`status` VARCHAR(180) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`error` VARCHAR(180) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`free` INT(11) NULL DEFAULT NULL,
`time` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
PRIMARY KEY (`id`),
INDEX `installers_created_at_index` (`created_at`),
INDEX `installers_updated_at_index` (`updated_at`),
INDEX `installers_driver_id_foreign` (`driver_id`),
INDEX `installers_success_index` (`success`),
INDEX `installers_version_index` (`version`),
INDEX `installers_pc_index` (`pc`(191)),
INDEX `installers_status_index` (`status`),
INDEX `installers_error_index` (`error`),
INDEX `installers_free_index` (`free`),
INDEX `installers_time_index` (`time`),
CONSTRAINT `installers_driver_id_foreign` FOREIGN KEY (`driver_id`) REFERENCES `drivers` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4709971
;
'free' 的不同值为 NULL,0,1
解决方案
NULL 不是值,NULL(根据WIKI - NULL):
Null(或 NULL)是结构化查询语言中使用的特殊标记,用于指示数据库中不存在数据值。
这不应与值 0 混淆。空值表示缺少值 — 缺少值与值 0 不同,就像缺少答案不一样事情作为“不”的答案。例如,考虑“亚当拥有多少本书?”这个问题。答案可能是“零”(我们知道他没有拥有)或“空”(我们不知道他拥有多少)。在数据库表中,报告此答案的列一开始将没有值(由 Null 标记),并且在我们确定 Adam 没有任何书籍之前,它不会更新为“零”值。
SQL null 是一个状态,而不是一个值。这种用法与大多数编程语言完全不同,其中引用的 null 值意味着它没有指向任何对象。
由于 Null 不是任何数据域的成员,因此它不被视为“值”,而是指示不存在值的标记(或占位符)。因此,与 Null 的比较永远不会导致 True 或 False,但总是会产生第三个逻辑结果 Unknown。
那是:
1 = 0
为假,但1 = NULL
未知1 != 0
是 TRUE 但1 != NULL
也是 UNKNOWN
WHERE 子句中的UNKNOWN
状态相当于 FALSE。
这是直观的——因为 x 为 NULL(未知),所以我们不能说 x = 1 或 x != 1 是否为真——在这两种情况下,比较结果都是未知的。
由于上述原因,SQL 中有特殊的运算符来检查列是否为空 -x IS NULL
和x IS NOT NULL
.
您可以在这个简单的演示中看到这种行为:http ://www.sqlfiddle.com/#!9/9f78b0/5
SELECT * FROM t;
| id | x |
|----|--------|
| 1 | 1 |
| 2 | 0 |
| 3 | (null) |
SELECT * FROM t WHERE x =1;
| id | x |
|----|---|
| 1 | 1 |
SELECT * FROM t WHERE x != 1;
| id | x |
|----|---|
| 2 | 0 |
请注意,上面的查询只返回了带有的记录,x = 2
但跳过了带有的记录,x = NULL
因为比较x != NULL
评估为 UNKNOWN,相当于 FALSE。
SELECT * FROM t WHERE x IS NULL;
| id | x |
|----|--------|
| 3 | (null) |
SELECT * FROM t WHERE x IS NOT NULL;
| id | x |
|----|---|
| 1 | 1 |
| 2 | 0 |
SELECT * FROM t WHERE x = 1 OR x IS NULL;
| id | x |
|----|--------|
| 1 | 1 |
| 3 | (null) |
SELECT * FROM t WHERE x != 1 OR x IS NULL;
| id | x |
|----|--------|
| 2 | 0 |
| 3 | (null) |
推荐阅读
- gatsby - 将 gatsby-plugin-transition-link 放入 gatsby.config 文件会导致整个网站崩溃
- bash - 运行带有setsid的shell脚本错误
- javascript - 如何在 Express API 中编写正确的 ES6 类?
- scala - 如何从作业上下文中获取提交 spark 作业的用户的详细信息?
- mysql - 在 SQL 中拆分名称
- swift - 当应用程序进入后台时,应用程序在前台使用带有 GPU 的 CoreML 无法切换到 CPU
- google-data-studio - 如何过滤分数以显示最新日期的摘要?
- javascript - ReactJS:来自多个 JSON 文件的下拉搜索结果
- git - 如何在 Web 浏览器中删除 github 存储库提交历史记录
- arrays - Rust:初始化二维数组