假设我们想从A表中选择一些记录,记录中的部分字段的取值是B表
所不存在的,这里定义A表为源表,B表为参照表。例如,常见的例子
部门表(Department)作为源表,员工表(Employee)作为参照表,可以
从部门表中列举出那些员工表中所不包含的部门id来,即找出那些没有
员工的部门。
一般类来说,如果数据库支持集合操作符,就可以直接查询,如果
没有,就使用子查询。
(1)
DB2 and PostgreSQL:
select deptno from dept
except
select deptno from emp
(2)
Oracle and Teradata:
select deptno from dept
minus
select deptno from emp
(3)
MySQL and SQL Server:
select deptno
from dept
where deptno not in (select deptno from emp)
SQL A:
select a.deptno from dept a where a.deptno
not in (select deptno from new_dept)
虽然源表中20,30,40这三个deptno都不存在于参照表中,但是上面这个SQL
的查询结果为空,一条记录也没有。
而想要得到需要的结果需要写成:SQL B
select a.deptno from dept a where a.deptno
not in (select deptno from new_dept where deptno is not null)
查询结果为 20,30,40三条记录
SQL A之所以没有任何结果的原因在于NULL, NOT,和OR的几个操作符的综合作用
首先IN操作符等价多个OR的并列,所以SQL A实际上等价为
A-1:
select a.deptno from dept a where a.deptno
not in(10,50,null)
A-2:
select deptno from dept where
not (deptno=10 or deptno=50 or deptno=null)
下面要注意,必须明确几个操作符之间的结果:
TRUE or NULL 结果是TRUE
FALSE or NULL 结果是NULL
NOT的运算结果
bool表达式 NOT 运算结果
TURE FALSE
FALSE TRUE
NULL NULL
尤其注意NOT对未知的字段运算结果还是NULL,这一点一定要和
IS NULL 和IS NOT NULL这个关键词组合区分开。
最后任何字段和NULL进行运算=,+,-,...结果都是NULL
这也是SQL里面强调用IS NULL和IS NOT NULL来区分字段是否为空
而不是用=来区分
明确了上面运算符的运算规则,我们来看
not (deptno=10 or deptno=50 or deptno=null)
当源表中deptno为10时,则
not ( TRUE or FALSE or NULL )
结果是 not (TRUE) -> FALSE 这条记录不会显示
当源表中dept为20时, 则
not ( FALSE or FALSE or NULL )
结果是 not (NULL) -> NULL
where的搜索条件是空,也不会有任何结果
(你可以尝试select * from dept where deptno=null这种sql看看结果)