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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คำค้นย่อยที่สัมพันธ์กัน
- EXISTS และ NOT EXISTS
- IN เทียบกับ ANY เทียบกับ ALL
- ประสิทธิภาพของ EXISTS เทียบกับ JOIN