ปรับปรุง:
บทความเหล่านี้ในบล็อกของฉันอธิบายความแตกต่างระหว่างวิธีการโดยละเอียดเพิ่มเติม:
มีสามวิธีในการค้นหาดังกล่าว:
LEFT JOIN / IS NULL:
SELECT *
FROM common
LEFT JOIN
table1 t1
ON t1.common_id = common.common_id
WHERE t1.common_id IS NULL
NOT EXISTS:
SELECT *
FROM common
WHERE NOT EXISTS
(
SELECT NULL
FROM table1 t1
WHERE t1.common_id = common.common_id
)
NOT IN:
SELECT *
FROM common
WHERE common_id NOT IN
(
SELECT common_id
FROM table1 t1
)
เมื่อtable1.common_idใดที่ไม่สามารถเป็นโมฆะได้แบบสอบถามเหล่านี้ทั้งหมดจะเหมือนกันอย่างมีความหมาย
เมื่อเป็นโมฆะNOT INจะแตกต่างกันเนื่องจากIN(และดังนั้นNOT IN) จะส่งคืนNULLเมื่อค่าไม่ตรงกับสิ่งใด ๆ ในรายการที่มี a NULL.
สิ่งนี้อาจทำให้สับสน แต่อาจชัดเจนมากขึ้นหากเราจำไวยากรณ์ทางเลือกสำหรับสิ่งนี้:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
ผลลัพธ์ของเงื่อนไขนี้เป็นผลคูณบูลีนของการเปรียบเทียบทั้งหมดภายในรายการ แน่นอนว่าNULLค่าเดียวให้NULLผลลัพธ์ซึ่งแสดงผลลัพธ์ทั้งหมดNULLด้วย
เราไม่เคยไม่สามารถพูดได้แน่นอนว่าจะไม่เท่ากับอะไรจากรายการนี้อย่างน้อยตั้งแต่ค่าใดค่าหนึ่งคือcommon_idNULL
สมมติว่าเรามีข้อมูลเหล่านี้:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULLและNOT EXISTSจะกลับมา3, NOT INจะกลับไม่มีอะไร (เพราะมันมักจะประเมินผลอย่างใดอย่างหนึ่งFALSEหรือNULL)
ในMySQLในกรณีที่คอลัมน์ไม่ใช่ nullable, LEFT JOIN / IS NULLและNOT INมีนิด ๆ หน่อย ๆ (ร้อยละหลาย) NOT EXISTSที่มีประสิทธิภาพมากกว่า ถ้าคอลัมน์เป็นโมฆะNOT EXISTSจะมีประสิทธิภาพมากที่สุด (อีกครั้งไม่มาก)
ในOracleแบบสอบถามทั้งสามให้ผลแผนเดียวกัน (an ANTI JOIN)
ในSQL Server, NOT IN/ NOT EXISTSมีประสิทธิภาพมากขึ้นเนื่องจากLEFT JOIN / IS NULLไม่สามารถเพิ่มประสิทธิภาพให้กับANTI JOINโดยการเพิ่มประสิทธิภาพของมัน
ในPostgreSQL, LEFT JOIN / IS NULLและNOT EXISTSมีประสิทธิภาพมากขึ้นกว่าNOT INไซน์พวกเขาจะปรับไปยังAnti Joinในขณะที่NOT INการใช้งานhashed subplan(หรือแม้กระทั่งธรรมดาsubplanถ้าแบบสอบถามย่อยที่มีขนาดใหญ่เกินไปที่จะกัญชา)