การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)
ค้นหา “แถวใน A ที่ไม่มีรายการตรงกันใน B” (การเชื่อมแบบตัดออก) และ “แถวใน A ที่มีรายการตรงกันอย่างน้อยหนึ่งรายการใน B” (กึ่งเชื่อม) ด้วย EXISTS/NOT EXISTS
การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS) เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
Semi-Join: "มีรายการที่ตรงกันอย่างน้อยหนึ่งรายการ"
คืนค่าแถวจาก A ที่มีแถวใน B ตรงกันอย่างน้อยหนึ่งแถว แต่คืนเฉพาะคอลัมน์ของ A เท่านั้น SQL ใช้ EXISTS หรือ IN เพื่อทำ semi-join
Semi-Join ด้วย EXISTS
ผู้ใช้ที่สั่งซื้ออย่างน้อยหนึ่งรายการ:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);Semi-Join ด้วย IN
ได้ผลลัพธ์เดียวกัน แต่ใช้รูปแบบต่างกัน:
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);เหตุใด EXISTS มักทำงานได้ดีกว่า
EXISTS หยุดการประเมินทันทีเมื่อพบรายการตรงกันรายการแรกของแต่ละแถวภายนอก ส่วน IN อาจสร้างชุดข้อมูลด้านในทั้งหมดไว้ในหน่วยความจำ ตัววางแผนสมัยใหม่มักปรับให้ได้แผนเดียวกัน แต่ EXISTS เป็นตัวเลือกที่ปลอดภัยกว่าสำหรับชุดข้อมูลด้านในขนาดใหญ่มาก
Anti-Join: "ไม่มีรายการที่ตรงกัน"
ผู้ใช้ที่ไม่เคยสั่งซื้อเลย — มีรูปแบบการเขียนที่ใช้กันอยู่สามแบบ:
-- NOT EXISTS (preferred):
SELECT u.* FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- LEFT JOIN ... IS NULL:
SELECT u.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
-- NOT IN (risky with NULLs):
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders);เหตุใด NOT IN จึงมีความเสี่ยง
หากคำค้นย่อยด้านในมี NULL, NOT IN จะคืนค่า NULL และ WHERE จะตัดแถวที่ predicate เป็น NULL ออก ผลลัพธ์คือไม่มีแถว NOT EXISTS ไม่มีปัญหานี้
การปรับให้เหมาะสมโดยตัววางแผน
PostgreSQL สมัยใหม่จะรู้จัก EXISTS และ NOT EXISTS ว่าเป็นรูปแบบ semi-join/anti-join และอาจประมวลผลด้วย hash join:
EXPLAIN ANALYZE
SELECT u.* FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- → Hash Anti JoinAnti-Join หลายคอลัมน์
ใช้คีย์ผสม:
SELECT * FROM order_items oi
WHERE NOT EXISTS (
SELECT 1 FROM shipments s
WHERE s.order_id = oi.order_id
AND s.line_no = oi.line_no
);Semi-Join ด้วย EXISTS + predicate เพิ่มเติม
เพิ่มตัวกรองให้กับคำค้นย่อยด้านใน:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
AND o.created_at >= NOW() - INTERVAL '30 days'
);สร้างดัชนีให้คอลัมน์ที่ใช้เชื่อมโยง
ทั้ง EXISTS และ NOT EXISTS จะกรองคำค้นย่อยด้านในโดยใช้คีย์ของแถวด้านนอก หากไม่มีดัชนีบนคีย์นั้น ระบบจะสแกนหนึ่งครั้งต่อแถวด้านนอก:
CREATE INDEX orders_user_id_idx ON orders(user_id);ควรใช้ LEFT JOIN ... IS NULL เมื่อใด
สำหรับแดชบอร์ดที่ต้องการคอลัมน์จากฝั่งที่ไม่มีรายการตรงกันด้วย รูปแบบ LEFT JOIN จะเหมาะอย่างเป็นธรรมชาติ แต่สำหรับความหมายของ anti-join โดยตรง NOT EXISTS จะชัดเจนกว่า
นอกเหนือจาก SQL: Bloom Filter
สำหรับ anti-join ขนาดใหญ่มาก การกรองเบื้องต้นด้วยตัวกรองบลูมอาจช่วยได้ PostgreSQL รองรับดัชนี bloom ผ่านส่วนขยาย bloom
สรุป
Semi-join = "มีรายการตรงกัน" ส่วน anti-join = "ไม่มีรายการตรงกัน"
- ใช้ EXISTS สำหรับ semi-join
- ใช้ NOT EXISTS สำหรับ anti-join (ปลอดภัยกับ NULL)
- สร้างดัชนีให้คอลัมน์ที่ใช้เชื่อมโยง
- หลีกเลี่ยง NOT IN เว้นแต่จะรับประกันว่าด้านในไม่มี NULL
ตรวจสอบความเข้าใจ
คุณต้องการผู้ใช้ที่ไม่เคยสั่งซื้อเลย SQL แบบใดปลอดภัยและเป็นสำนวนที่เหมาะสมที่สุด
คำถามที่พบบ่อย
บทเรียน “การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)”
ค้นหา “แถวใน A ที่ไม่มีรายการตรงกันใน B” (การเชื่อมแบบตัดออก) และ “แถวใน A ที่มีรายการตรงกันอย่างน้อยหนึ่งรายการใน B” (กึ่งเชื่อม) ด้วย EXISTS/NOT EXISTS คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม
ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การเชื่อมแบบ Cross และผลคูณคาร์ทีเซียน
- การเชื่อมแบบ Lateral (LATERAL JOIN)
- การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)
- การปรับประสิทธิภาพการเชื่อมหลายตาราง