建表语句:https://blog.csdn.net/karive/article/details/105055038
常见写法:
SELECT DISTINCT JNO FROM SPJ,S WHERE S.SNO=SPJ.SNO AND S.CITY<>'天津' SELECT DISTINCT JNO FROM J WHERE JNO NOT IN(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO ); SELECT DISTINCT JNO FROM SPJ WHERE JNO NOT IN(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO ); SELECT DISTINCT JNO FROM J WHERE NOT EXISTS(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO AND J.JNO=SPJ.JNO); SELECT DISTINCT JNO FROM SPJ WHERE NOT EXISTS(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO );
执行结果:(SQL Server 2019)
结果分析:
第一种方法:错。
SELECT DISTINCT JNO FROM SPJ,S WHERE S.SNO=SPJ.SNO AND S.CITY<>'天津'
原因在于,如果同一个工程同时使用了“天津的零件”和“不是天津的零件”的,也会在结果中。但是,根据语义,只要使用了“天津的零件”,就不能在结果中。因此,方法一是错误的。
第二种方法:对。
SELECT DISTINCT JNO FROM J WHERE JNO NOT IN(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO );
第三种方法:错。
SELECT DISTINCT JNO FROM SPJ WHERE JNO NOT IN(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO );
跟第二种方法比较,From来自于SPJ而不是J,这样的话,J表中的部分数据会丢失。
第四种方法:对。
SELECT DISTINCT JNO FROM J WHERE NOT EXISTS(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO AND J.JNO=SPJ.JNO);
第五种方法:错。
SELECT DISTINCT JNO FROM SPJ WHERE NOT EXISTS(SELECT JNO FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO );
错误的原因:不相关子查询。内层只要有结果(不为空),那么,NOT EXISTS 之后,最终结果就全部为空。
如果觉得不好理解,可以吧NOT EXISTS换为EXISTS试一下:
SELECT DISTINCT JNO FROM SPJ WHERE EXISTS(SELECT * FROM S,SPJ WHERE CITY='天津'AND S.SNO=SPJ.SNO );
结果如下:
为什么是所有SPJ中的JNO? 原因在于,内层结果为真,所以显示全部数据。
这种写法,只看内层的结果是否有天津供应的零件:SPJ所有的元组中,有1个或者多个天津供应的零件,就是真;SPJ所有的元组中,完全不存在(0个)天津供应的零件,就是假。
这与题目是不相符的,所以是错误的。