0Pricing
SQL Academy · บทเรียน

การเชื่อมแบบตัดออกและกึ่งเชื่อม (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 Join

Anti-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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การเชื่อมแบบ Cross และผลคูณคาร์ทีเซียน
  2. การเชื่อมแบบ Lateral (LATERAL JOIN)
  3. การเชื่อมแบบตัดออกและกึ่งเชื่อม (NOT EXISTS)
  4. การปรับประสิทธิภาพการเชื่อมหลายตาราง
← กลับไปที่ SQL Academy