建表語句: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個)天津供應的零件,就是假。
這與題目是不相符的,所以是錯誤的。