查询条件,如果列中有NULL值

时间:2018-08-23 15:03:10

标签: mysql sql

我不了解两个查询之间的区别,请参见图片。 注意最后的条件。 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)

(free为null或free = 0)

enter image description here

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

enter image description here

表结构

    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

2 个答案:

答案 0 :(得分:2)

NULL不是值NULL(根据WIKI - NULL):

  

空(或NULL)是结构化查询语言中使用的特殊标记   表示数据库中不存在数据值。

     

请勿将其与0值混淆。空值表示   缺乏价值-缺乏价值与价值不一样   零的答案与缺少答案的方法不同   作为“否”的答案。例如,请考虑以下问题:   亚当拥有书籍吗?”答案可能是“零”(我们知道他拥有   无)或“空”(我们不知道他拥有多少)。在数据库中   表中,报告此答案的列将开始时没有值   (由Null标记),并且不会使用“零”值进行更新   直到我们确定亚当没有书为止。

     

SQL null是状态,而不是值。这种用法与   大多数编程语言,其中引用的空值表示它   没有指向任何对象。

     

由于Null不是任何数据域的成员,因此不将其视为   “值”,而是表示缺少的标记(或占位符)   价值。因此,与Null的比较永远不会导致   是或否,但总是在第三个逻辑结果中,   未知。

也就是说:

  • 1 = 0为假,但1 = NULL为未知
  • 1 != 0为TRUE,但1 != NULL也不为人

WHERE子句中的UNKNOWN状态等效于FALSE。

这很直观-因为x为NULL(未知),所以我们不能说x = 1还是x!= 1为真-在两种情况下,比较结果都是未知的。

由于上述原因,SQL中有一些特殊的运算符可以检查列是否为空-x IS NULLx 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) |

答案 1 :(得分:0)

在使用INT(11)时, free 列中的值可以在-2147483648和2147483647之间

free 列的默认值为 NULL (表示未知或未设置,不表示0或任何已知数字,注意:始终为NULL = NULL false ,因为NULL不等于NULL)

因此,当您使用free=0 or free is null语句时,它表示free仅等于0或未设置free时(NULL),否则为 false

但是当您使用free!=1时,如果free为0,-1,4145和...,则为 true 每个已知的数字,但1 AND NULL

PS:两者都可以是true,这取决于您要从查询中获得什么 如果free仅在free时为1,否则为0或NULL,则free=0 or free is null是正确的语句。但是对于MySQL手册中的布尔值,您可以使用Bool和Boolean, tinyint的瞬间别名:

  

布尔型,布尔型:这些类型是TINYINT(1)的同义词。值   零被认为是错误的。非零值被认为是正确的。