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

EXISTS และ NOT EXISTS

ตรวจสอบแถวที่เกี่ยวข้องอย่างมีประสิทธิภาพ

EXISTS และ NOT EXISTS เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

EXISTS คืออะไร

ตัวดำเนินการ EXISTS ใช้ทดสอบว่าคิวรีย่อยคืนค่าอย่างน้อยหนึ่งแถวหรือไม่ โดยจะประเมินเป็น TRUE หากคิวรีย่อยสร้างผลลัพธ์ใด ๆ และเป็น FALSE หากคิวรีย่อยไม่มีผลลัพธ์

แตกต่างจากตัวดำเนินการคิวรีย่อยอื่น ๆ ที่ใช้เปรียบเทียบค่า EXISTS สนใจเพียง การมีอยู่ เท่านั้น ไม่ได้ตรวจสอบข้อมูลจริงที่คิวรีย่อยคืนมา

การเตรียมตารางตัวอย่าง

ก่อนเขียนคิวรี EXISTS มาสร้างตารางสองตารางกัน ได้แก่ customers และ orders เราจะใช้ตารางเหล่านี้ตลอดบทเรียน เพื่อสำรวจการทำงานของ EXISTS และ NOT EXISTS ในทางปฏิบัติ

CREATE TABLE customers (
  customer_id INT PRIMARY KEY,
  name        VARCHAR(100),
  country     VARCHAR(50)
);

CREATE TABLE orders (
  order_id    INT PRIMARY KEY,
  customer_id INT,
  amount      DECIMAL(10,2),
  order_date  DATE
);

INSERT INTO customers VALUES
  (1, 'Alice',   'US'),
  (2, 'Bob',     'UK'),
  (3, 'Charlie', 'US'),
  (4, 'Diana',   'DE');

INSERT INTO orders VALUES
  (101, 1, 250.00, '2024-01-10'),
  (102, 1, 180.00, '2024-02-15'),
  (103, 2,  95.00, '2024-03-01'),
  (104, 3, 430.00, '2024-03-22');

ไวยากรณ์พื้นฐานของ EXISTS

ไวยากรณ์พื้นฐานของ EXISTS คือการวางไว้ภายในส่วนคำสั่ง WHERE โดยปกติคิวรีย่อยภายใน EXISTS จะอ้างอิงคอลัมน์จากคิวรีภายนอก ซึ่งเรียกว่า คิวรีย่อยที่สัมพันธ์กัน

คิวรีด้านล่างจะค้นหาลูกค้าทุกคนที่สั่งซื้ออย่างน้อยหนึ่งรายการ

SELECT customer_id, name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
);

การใช้ SELECT 1 ภายใน EXISTS

คุณอาจสังเกตว่าแบบสอบถามย่อยใช้ SELECT 1 แทนการเลือกคอลัมน์จริงใด ๆ นี่เป็นการตั้งใจ — EXISTS ตรวจสอบเพียงว่าแถว มีอยู่ หรือไม่ ไม่ได้ตรวจสอบว่าแถวนั้นมีข้อมูลอะไร

การใช้ SELECT 1 (หรือแม้แต่ SELECT *) ไม่ทำให้ผลลัพธ์แตกต่างกัน แต่ SELECT 1 สื่อให้ทั้งกลไกฐานข้อมูลและผู้อ่านเห็นอย่างชัดเจนว่าค่าจริงไม่มีความสำคัญ

-- Both of these return the same result
SELECT name FROM customers c
WHERE EXISTS (SELECT 1   FROM orders o WHERE o.customer_id = c.customer_id);

SELECT name FROM customers c
WHERE EXISTS (SELECT o.* FROM orders o WHERE o.customer_id = c.customer_id);

ฐานข้อมูลประเมิน EXISTS อย่างไร

สำหรับทุกแถวในแบบสอบถามภายนอก ฐานข้อมูลจะเรียกใช้แบบสอบถามย่อยที่สัมพันธ์กัน ทันทีที่พบแถวที่ตรงกันหนึ่งแถว กลไกจะหยุดสแกนและกำหนดให้ EXISTS เป็น TRUE — การประเมินแบบลัดวงจรนี้ทำให้ EXISTS มีประสิทธิภาพสูงมาก แม้ใช้กับตารางขนาดใหญ่

ในทางกลับกัน JOIN จะสร้างชุดแถวที่ตรงกันทั้งหมดก่อนกรอง ซึ่งอาจช้ากว่าเมื่อคุณต้องการเพียงตรวจสอบว่ามีรายการที่ตรงกันหรือไม่

-- EXISTS short-circuits after first match
-- Efficient even when orders table has millions of rows
SELECT name, country
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
    AND o.amount > 200
);

NOT EXISTS: ค้นหาแถวที่ไม่พบ

NOT EXISTS เป็นการทำงานตรงข้าม โดยจะส่งคืนค่า TRUE เมื่อแบบสอบถามย่อยไม่พบแถวที่ตรงกันเลย นี่คือวิธีมาตรฐานของ SQL สำหรับตอบคำถามอย่างเช่น "ลูกค้ารายใดไม่เคยสั่งซื้อเลย"

การพยายามแก้ปัญหานี้ด้วย JOIN ปกติหรือ NOT IN อาจให้ผลลัพธ์ไม่ถูกต้องเมื่อมี NULL เข้ามาเกี่ยวข้อง — NOT EXISTS หลีกเลี่ยงปัญหานี้ได้ทั้งหมด

-- Customers who have NOT placed any order
SELECT customer_id, name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
);

NOT EXISTS เทียบกับ NOT IN เมื่อมี NULL

ข้อได้เปรียบสำคัญประการหนึ่งของ NOT EXISTS เหนือ NOT IN คือความปลอดภัยเมื่อมีค่า NULL หากแบบสอบถามย่อยที่ใช้โดย NOT IN ส่งคืนค่า NULL แม้เพียงหนึ่งค่า นิพจน์ NOT IN ทั้งหมดจะกลายเป็น NULL — ซึ่งหมายความว่าแบบสอบถามภายนอกจะไม่ส่งคืนแถวใดเลย

NOT EXISTS ไม่ได้รับผลกระทบจากปัญหานี้ เพราะประเมินการมีอยู่ของแถว ไม่ใช่ความเท่ากันของค่า

-- Dangerous: if any customer_id in orders is NULL,
-- NOT IN returns zero rows!
SELECT name FROM customers
WHERE customer_id NOT IN (SELECT customer_id FROM orders);

-- Safe: NOT EXISTS handles NULLs correctly
SELECT name FROM customers c
WHERE NOT EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.customer_id
);

EXISTS กับเงื่อนไขหลายรายการ

แบบสอบถามย่อยภายใน EXISTS สามารถมี SQL ที่ถูกต้องรูปแบบใดก็ได้ รวมถึงเงื่อนไข WHERE หลายรายการ ทำให้คุณตรวจสอบแถวที่เกี่ยวข้องได้อย่างเฉพาะเจาะจงมากขึ้น ตัวอย่างเช่น ลูกค้าที่สั่งซื้อเกินเกณฑ์ที่กำหนดในเดือนที่ระบุ

-- Customers who placed an order over 200 in March 2024
SELECT c.name, c.country
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.customer_id
    AND o.amount > 200
    AND o.order_date >= '2024-03-01'
    AND o.order_date <  '2024-04-01'
);

EXISTS ใน DELETE และ UPDATE

EXISTS ไม่ได้จำกัดเฉพาะคำสั่ง SELECT คุณสามารถใช้ใน UPDATE และ DELETE เพื่อแก้ไขหรือลบแถวโดยอิงจากการมีอยู่ของข้อมูลที่เกี่ยวข้องในอีกตารางหนึ่ง

ตัวอย่างด้านล่างลบคำสั่งซื้อที่เป็นของลูกค้าจากประเทศที่ระบุ

-- Delete orders placed by US customers
DELETE FROM orders o
WHERE EXISTS (
  SELECT 1
  FROM customers c
  WHERE c.customer_id = o.customer_id
    AND c.country = 'US'
);

เปรียบเทียบ EXISTS กับ JOIN

EXISTS และ JOIN มักใช้สื่อคำถามเดียวกันได้ แต่มีพฤติกรรมต่างกัน JOIN จะทำให้จำนวนแถวเพิ่มขึ้นเมื่อมีรายการที่ตรงกันหลายรายการ ส่วน EXISTS จะส่งคืนแถวภายนอกแต่ละแถวไม่เกินหนึ่งครั้ง

เมื่อคุณต้องการทราบเพียงว่า มีความสัมพันธ์อยู่หรือไม่ (ไม่ใช่ดึงข้อมูลจากตารางที่เกี่ยวข้อง) EXISTS จะอ่านเข้าใจง่ายกว่าและโดยทั่วไปทำงานได้เร็วกว่า

-- JOIN may return duplicate customer rows if a customer has multiple orders
SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id;

-- EXISTS always returns each customer once
SELECT c.name
FROM customers c
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.customer_id
);

NOT EXISTS สำหรับตรวจสอบคุณภาพข้อมูล

NOT EXISTS เป็นเครื่องมือทรงพลังสำหรับการตรวจสอบคุณภาพข้อมูล คุณสามารถใช้ค้นหาระเบียนกำพร้า การอ้างอิงที่หายไป หรือแถวที่ควรมีข้อมูลที่เกี่ยวข้องแต่ไม่มี

แบบสอบถามด้านล่างตรวจหาแถวคำสั่งซื้อที่ customer_id ไม่ตรงกับแถวใดเลยในตารางลูกค้า ซึ่งเป็นสัญญาณว่าความถูกต้องของการอ้างอิงเสียหาย

-- Find orders with no matching customer (orphaned records)
SELECT o.order_id, o.customer_id, o.amount
FROM orders o
WHERE NOT EXISTS (
  SELECT 1
  FROM customers c
  WHERE c.customer_id = o.customer_id
);

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจของคุณเกี่ยวกับ EXISTS และ NOT EXISTS

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า EXISTS และ NOT EXISTS ช่วยให้ตรวจสอบการมีอยู่หรือการไม่อยู่ของแถวที่เกี่ยวข้องได้ โดยไม่ต้องเปรียบเทียบค่าโดยตรง

ประเด็นสำคัญ:

  • EXISTS จะส่งคืนค่า TRUE ทันทีที่แบบสอบถามย่อยพบแถวที่ตรงกันหนึ่งแถว (การประเมินแบบลัดวงจร)
  • NOT EXISTS จะส่งคืนค่า TRUE เมื่อแบบสอบถามย่อยไม่พบแถวที่ตรงกัน
  • ใช้ SELECT 1 ภายใน EXISTS — ค่าที่ส่งคืนไม่มีความสำคัญ
  • NOT EXISTS ปลอดภัยเมื่อมี NULL ส่วน NOT IN ไม่เป็นเช่นนั้น — ควรเลือก NOT EXISTS เมื่ออาจมี NULL
  • EXISTS ใช้ได้ในคำสั่ง SELECT, UPDATE และ DELETE
  • เมื่อคุณต้องการเพียงตรวจสอบการมีอยู่ EXISTS มักอ่านเข้าใจง่ายและทำงานได้เร็วกว่า JOIN

คำถามที่พบบ่อย

บทเรียน “EXISTS และ NOT EXISTS” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “EXISTS และ NOT EXISTS” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “EXISTS และ NOT EXISTS”

ตรวจสอบแถวที่เกี่ยวข้องอย่างมีประสิทธิภาพ คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “EXISTS และ NOT EXISTS” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม

ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. คำค้นย่อยที่สัมพันธ์กัน
  2. EXISTS และ NOT EXISTS
  3. IN เทียบกับ ANY เทียบกับ ALL
  4. ประสิทธิภาพของ EXISTS เทียบกับ JOIN
← กลับไปที่ SQL Academy