3.1 Not In与null
  在下面这个查询中,where子句中使用not in来过滤数据,where子句的条件是OrderStatus not in ('Active','InActive'),我们期望结果集中包含orderstatus为'Not Active'、'NULL'这两行的数据。
  select * from orders where OrderStatus not in ('Active','InActive')
  这个查询中,当OrderStatus为null时, 原where子句等价于where null <>'Active' AND  null<>'InActive',这变成了上文中介绍的比较运算与null的问题。where的判断结果还是null,所以该行不会出现在结果集中。而当OrderStatus为'Not Active'时,满足where筛选的为true的条件,会显示在结果集中。
  终,正确答案是:只有一行。

  说明:in与null的关系与此同理。
  3.2 Not exists与null
  现在我们还是期望结果集中包含orderstatus为'Not Active'、'NULL'这两行的数据,这次用Not exists。
  在这个查询中,子查询先求出OrderStatus='Active' or  OrderStatus='InActive的行,然后外部查询用not exists过滤子查询的结果,将剩下的行显示在终结果集中。
  SELECT *
  FROM orders AS o1
  WHERE NOT EXISTS(
  SELECT *
  FROM orders AS o2
  WHERE o1.OrderStatus = o2.OrderStatus
  AND ( o2.OrderStatus = 'Active'
  OR o2.OrderStatus = 'InActive'
  ));

  为了方便理解,我们将子查询改写成自表连接的方式,
  select * from orders as o2 where  o1.OrderStatus=o2.OrderStatus and (o2.OrderStatus='Active' or  o2.OrderStatus='InActive' ))
  改写成:
  SELECT *
  FROM orders AS o2
  INNER JOIN orders o1 ON o1.OrderStatus = o2.OrderStatus
  AND ( o2.OrderStatus = 'Active'
  OR o2.OrderStatus = 'InActive'
  );
  返回的结果集为:

  然后我们再看外层查询,
  外部查询期望使用not exists返回orders表中不包含子查询结果集的行,也是说,只要orders表没有子查询结果集中的行返回true,否则返回false(只有存在和不存在,没有unknown的说法)。
  按照这个逻辑,orderID为3和4的行不在子查询的结果集中,因此not exists判断为true,而orderID为1和2的行已包含在子查询的结果集中,所以not exists判断为false。后根据where筛选“接受true,拒绝false和null”的原则,终只有orderID为3和4的行显示在结果集中。


  说明:exists与null的关系与此同理。
  3.3 Not  in和Not exists的区别
  not in实际上是对一个对象的比较运算,而比较存在true|false|unknow三种逻辑值。
  not exsits判断某个对象存在或者不存在,它只有这两种状态,没有unknown的说法。因此相比not in而言,not exists只会有true和false这两种逻辑值。
  总结:
  上文介绍了null在不同场景中的含义,考虑到SQL不同的语言元素对null的不同处理方式,平常我们在写SQL语句的时候应该清晰思考自己编写的每个查询对null或三值逻辑的处理,避免出现逻辑错误。