ตัวEXCEPT
ดำเนินการถูกนำมาใช้ใน SQL Server 2005 แต่ความแตกต่างระหว่างNOT IN
และEXCEPT
คืออะไร
มันทำเช่นเดียวกัน? ฉันต้องการคำอธิบายง่ายๆพร้อมตัวอย่าง
ตัวEXCEPT
ดำเนินการถูกนำมาใช้ใน SQL Server 2005 แต่ความแตกต่างระหว่างNOT IN
และEXCEPT
คืออะไร
มันทำเช่นเดียวกัน? ฉันต้องการคำอธิบายง่ายๆพร้อมตัวอย่าง
คำตอบ:
มีสองความแตกต่างที่สำคัญระหว่างมีและEXCEPT
NOT IN
EXCEPT
กรองDISTINCT
ค่าจากตารางด้านซ้ายที่ไม่ปรากฏในตารางทางขวา มันเป็นหลักเช่นเดียวกับการทำNOT EXISTS
ด้วยDISTINCT
ประโยค
นอกจากนี้ยังคาดว่าทั้งสองตาราง (หรือส่วนย่อยของคอลัมน์จากตาราง) จะมีจำนวนคอลัมน์เท่ากันในด้านซ้ายและด้านขวาของแบบสอบถาม
ตัวอย่างเช่นคุณไม่สามารถทำได้:
SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB
สิ่งนี้จะส่งผลให้เกิดข้อผิดพลาด:
แบบสอบถามทั้งหมดที่รวมกันโดยใช้ตัวดำเนินการ UNION, INTERSECT หรือ EXCEPT จะต้องมีจำนวนนิพจน์ที่เท่ากันในรายการเป้าหมาย
NOT IN
ไม่กรองDISTINCT
ค่าและส่งคืนค่าทั้งหมดจากตารางด้านซ้ายที่ไม่ปรากฏในตารางด้านขวา
NOT IN
คุณต้องการเปรียบเทียบคอลัมน์เดียวจากตารางหนึ่งกับคอลัมน์เดียวจากตารางหรือแบบสอบถามย่อยอื่น
ตัวอย่างเช่นหากแบบสอบถามย่อยของคุณส่งคืนคอลัมน์หลายคอลัมน์:
SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)
คุณจะได้รับข้อผิดพลาดดังต่อไปนี้:
สามารถระบุได้เพียงนิพจน์เดียวในรายการที่เลือกเมื่อไม่ได้แนะนำเคียวรีย่อยด้วย EXISTS
อย่างไรก็ตามหากตารางด้านขวามี a NULL
ในค่าที่ถูกกรองโดยNOT IN
ชุดผลลัพธ์ที่ว่างเปล่าจะถูกส่งกลับอาจทำให้ได้ผลลัพธ์ที่ไม่คาดคิด
CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);
INSERT INTO #NewCustomers
( ID )
VALUES
(8), (9), (10), (1), (3), (8);
INSERT INTO #ExistingCustomers
( ID )
VALUES
( 1) , (2), (3), (4), (5);
-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
จากแบบสอบถามสองข้อด้านบนให้EXCEPT
ส่งคืน 3 แถวจาก#NewCustomers
กรอง 1 และ 3 ที่ตรงกัน#ExistingCustomers
และซ้ำ 8
NOT IN
ไม่ทำการกรองที่แตกต่างกันและส่งคืน 4 แถวจาก#NewCustomers
ด้วยซ้ำ 8
หากเราเพิ่มใน a NULL
ไปยัง#ExistingCustomers
ตารางเราจะเห็นผลลัพธ์เดียวกันที่ส่งคืนโดยEXCEPT
อย่างไรก็ตามNOT IN
จะส่งคืนชุดผลลัพธ์ที่ว่างเปล่า
INSERT INTO #ExistingCustomers
( ID )
VALUES
( NULL );
-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;
แทนที่จะNOT IN
คุณจริงๆควรดูที่NOT EXISTS
และมีการเปรียบเทียบที่ดีระหว่างสองบล็อกเกลชอว์
การเพิ่มความคิดเห็นที่ยอดเยี่ยมของ Mark Sinkinson:
NOT IN กำหนดให้คุณเปรียบเทียบคอลัมน์เดียวจากตารางหนึ่งกับคอลัมน์เดียวจากตารางหรือแบบสอบถามย่อยอื่น
จริงๆแล้วคุณสามารถทำได้NOT IN
โดยมีมากกว่าหนึ่งคอลัมน์
เช่นนี้เป็นแบบสอบถาม SQL * ที่ถูกกฎหมาย:
SELECT E.first_name, E.last_name
FROM employees E
WHERE (E.first_name, E.last_name) NOT IN
(SELECT M.first_name, M.last_name FROM managers M)
ซึ่งจะส่งคืนfirst_name
และlast_name
จากทุกคนที่เป็นพนักงาน แต่ไม่ใช่ผู้จัดการ
*: แต่การก่อสร้างยังไม่ได้นำมาใช้ใน SQL Server
NOT IN ด้านบนล้มเหลวเนื่องจากจำเป็นต้องมีความสัมพันธ์ระหว่างเพรดิเคตในเคียวรีหลักและเคียวรีย่อย ถ้าคุณปล่อยให้มันออกคุณจะได้รับแบบสอบถามย่อยที่ไม่เกี่ยวข้อง
SELECT * จาก TableA AS nc ที่ ID ไม่อยู่ใน (เลือก ID, ชื่อจาก TableB AS ec โดยที่ nc.ID = ec.ID)
ยกเว้นจะดีกว่าและจะจัดการกับแถว null ใด ๆ โดยไม่ใช้ IS NULL / IS ไม่ใช่เพรดิเคตที่เป็นโมฆะ