2-3逻辑运算符

SQL
Author

Rui

Published

November 10, 2022

2-3 逻辑运算符

除了上一节介绍的 <> 比较运算符以外,NOT 运算符也可以表示否定,但需要同其他查询条件联用:

SELECT product_name, product_type, sale_price
  FROM Product
 WHERE sale_price >= 1000;
4 records
product_name product_type sale_price
T恤衫 衣服 1000
运动T恤 衣服 4000
菜刀 厨房用具 3000
高压锅 厨房用具 6800

添加 NOT:

 SELECT product_name, product_type, sale_price
   FROM Product
  WHERE NOT sale_price >= 1000;
4 records
product_name product_type sale_price
打孔器 办公用品 500
叉子 厨房用具 500
擦菜板 厨房用具 880
圆珠笔 办公用品 100
Note

R 中与之类似的代码是:Product[!(Product$sale_price >= 1000), ],或者使用 tidyverse :Product %>% filter(!(sale_price >= 1000))

等价于:

SELECT product_name, product_type, sale_price
  FROM Product
 WHERE sale_price < 1000;
4 records
product_name product_type sale_price
打孔器 办公用品 500
叉子 厨房用具 500
擦菜板 厨房用具 880
圆珠笔 办公用品 100
Tip

可以不使用 NOT 的时候尽量不要使用,毕竟逻辑转换是一件让人头大的事情。

AND 与 OR

在 WHERE 子句中使用 AND 和 OR 来组合多个条件:

  • AND 运算符代表”和”,只有两侧条件同时为真时才返回真。从集合的视角看,相当于取交集

  • OR 运算符代表”或”,只要两侧条件中有一个为真就返回真。从集合的视角看,相当于取并集

SELECT product_name, purchase_price
  FROM Product
 WHERE sale_price >= 3000 
   AND product_type = '厨房用具';
2 records
product_name purchase_price
菜刀 2800
高压锅 5000
SELECT product_name, purchase_price
  FROM Product
 WHERE sale_price >= 3000 
    OR product_type = '厨房用具';
5 records
product_name purchase_price
运动T恤 2800
菜刀 2800
高压锅 5000
叉子 NA
擦菜板 790

使用括号提高优先级

查询条件:“商品种类为办公用品”并且”登记日期是2009年9月11日或者2009年9月20日”

查询结果:符合上述条件的商品(product_name)只有”打孔器”

错误的方法:

SELECT product_name, product_type, regist_date
  FROM Product
 WHERE product_type = '办公用品'
   AND regist_date = '2009-09-11'
    OR regist_date = '2009-09-20';
4 records
product_name product_type regist_date
T恤衫 衣服 2009-09-20
打孔器 办公用品 2009-09-11
菜刀 厨房用具 2009-09-20
叉子 厨房用具 2009-09-20

这是因为 AND 在前 OR 在后导致 AND 的优先级比 OR 高,该查询的过程是先实现 AND 查询,再在 AND 查询的结果中实现 OR 查询。

正确的做法:

SELECT product_name, product_type, regist_date
  FROM Product
 WHERE product_type = '办公用品'
   AND (regist_date = '2009-09-11'
        OR regist_date = '2009-09-20');
1 records
product_name product_type regist_date
打孔器 办公用品 2009-09-11

使用括号提高 OR 的优先级。

逻辑运算符和真值

  • 真 = TRUE = 1

  • 假 = FALSE = 0

AND(逻辑积)
P Q P AND Q
1 1 1 1
1 0 0 0
0 1 0 0
0 0 0 0
OR(逻辑和)
P Q P OR Q
1 1 1 + 1 1
1 0 1 1
0 1 1 1
0 0 0 0

由 OR 的定义可知:真 + 假 = 1 + 0 = 1.

所以:真 = 1 - 假 = 1 - 0 = 1,假 = 1 - 真 = 1 - 1 = 0.

NOT
P NOT P
1 1 - 1 0
0 1 - 0 1

含有 NULL 时的真值\(^*\)

上一节讲过对于 NULL 的比较运算使用 IS NULL 或者 IS NOT NULL,其逻辑运算一样特殊。

注意到商品”叉子”和”圆珠笔”的价格都为 NULL,若对这两条记录使用查询条件 purchase_price = 2800 则返回假;但若对这两条记录使用查询条件 NOT purchase_price = 2800 则还是返回假。也就是说对于 purchase_price = 2800,结果既非真又非假。

这种情况是 SQL 中的除真假之外的第三种值——不确定(UNKNOWN)。 一般的逻辑运算为二值运算,SQL 中的逻辑运算为三值运算

如何理解:

  • 真(1)和假(0)都是确定的状态,而 NULL 是不确定的状态(混沌的)。NULL 就像薛定谔的猫,不到打开箱子看到它的真面目时谁也不知道它是真是假,只有打开箱子的那一刹那才能获知它的状态,但是那时它就不是 UNKNOWN 了;

  • 一个 NULL 和一个确定的数值进行比较判断,结果自然是不确定的(UNKNOWN)。同理一个 NULL 与另一个 NULL 进行比较判断,结果还是不确定的(UNKNOWN);

那么包含 NULL 的逻辑判断是怎样的呢?其实利用 AND 与 OR 的定义结合 NULL 的特性不难得出:

AND
P Q P AND Q
不确定 不确定
不确定
不确定 不确定
不确定
不确定 不确定 不确定
OR
P Q P OR Q
不确定
不确定 不确定
不确定
不确定 不确定
不确定 不确定 不确定

可以看出,在引入”不确定”后,逻辑判断变得复杂许多。为了避免出现这种情况,一般在创建表的时候为某些列设置 NOT NULL 约束以禁止录入 NULL。