คำค้นย่อยที่สัมพันธ์กัน
คำค้นย่อยที่ขึ้นอยู่กับแถวภายนอก
คำค้นย่อยที่สัมพันธ์กัน เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
คิวรีย่อยที่สัมพันธ์กันคืออะไร
คิวรีย่อยที่สัมพันธ์กัน คือคิวรีย่อยที่อ้างอิงคอลัมน์จากคิวรีภายนอกหรือคิวรีที่ครอบอยู่ ซึ่งแตกต่างจากคิวรีย่อยทั่วไปที่ทำงานครั้งเดียวและคืนผลลัพธ์คงที่ คิวรีย่อยที่สัมพันธ์กันจะถูกประเมินผล หนึ่งครั้งต่อทุกแถว ที่คิวรีภายนอกประมวลผล
คุณสมบัตินี้ทำให้เหมาะสำหรับการเปรียบเทียบข้อมูลทีละแถว แต่ก็ใช้ทรัพยากรมากกว่าคิวรีย่อยแบบง่าย
คิวรีย่อยทั่วไปเปรียบเทียบกับคิวรีย่อยที่สัมพันธ์กัน
ความแตกต่างสำคัญคือ คิวรีย่อยทั่วไปไม่มีการอ้างอิงไปยังคิวรีภายนอกและสามารถทำงานได้โดยลำพัง ส่วนคิวรีย่อยที่สัมพันธ์กัน ขึ้นอยู่กับ แถวภายนอก คุณจะเห็นนามแฝงของตารางภายนอกปรากฏอยู่ภายในคิวรีย่อย
ในตัวอย่างด้านล่าง SELECT ภายในอ้างอิง e1.department_id จากคิวรีภายนอก จึงทำให้เกิดความสัมพันธ์ขึ้น
-- Regular subquery (runs once)
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- Correlated subquery (runs once per outer row)
SELECT name, salary, department_id
FROM employees e1
WHERE salary > (
SELECT AVG(salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
);การเตรียมตารางตัวอย่าง
มาสร้างตารางสองตารางที่จะใช้ตลอดบทเรียนนี้กัน ได้แก่ employees และ departments ตารางเหล่านี้มีข้อมูลสมจริงสำหรับสาธิตคิวรีย่อยที่สัมพันธ์กันในสถานการณ์ต่าง ๆ
CREATE TABLE departments (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
department_id INT REFERENCES departments(id),
salary NUMERIC(10,2),
hire_date DATE
);
INSERT INTO departments VALUES (1,'Engineering'),(2,'Sales'),(3,'HR');
INSERT INTO employees VALUES
(1,'Alice', 1, 90000, '2020-03-01'),
(2,'Bob', 1, 75000, '2021-06-15'),
(3,'Carol', 2, 60000, '2019-01-10'),
(4,'David', 2, 68000, '2022-09-01'),
(5,'Eve', 3, 55000, '2020-07-20'),
(6,'Frank', 1, 95000, '2018-11-05'),
(7,'Grace', 3, 52000, '2023-02-28'),
(8,'Henry', 2, 71000, '2021-04-12');พนักงานที่มีรายได้สูงกว่าค่าเฉลี่ยของแผนก
กรณีใช้งานคลาสสิกของคิวรีย่อยที่สัมพันธ์กันคือ การค้นหาพนักงานทุกคนที่มีเงินเดือนสูงกว่าเงินเดือนเฉลี่ยของแผนกตนเอง คิวรีภายในจะคำนวณเงินเดือนเฉลี่ยของแผนกใหม่ สำหรับแถวพนักงานแต่ละแถว ในคิวรีภายนอก
SELECT e1.name, e1.department_id, e1.salary
FROM employees e1
WHERE e1.salary > (
SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
)
ORDER BY e1.department_id, e1.salary DESC;การใช้คิวรีย่อยที่สัมพันธ์กันใน SELECT
คิวรีย่อยที่สัมพันธ์กันไม่ได้จำกัดอยู่แค่ส่วนคำสั่ง WHERE แต่ยังปรากฏใน รายการ SELECT เพื่อคำนวณค่าสำหรับแต่ละแถวได้ ในที่นี้ เราดึงเงินเดือนของพนักงานแต่ละคนพร้อมเงินเดือนเฉลี่ยของแผนกมาแสดงในคิวรีเดียว
SELECT
e.name,
e.salary,
(
SELECT ROUND(AVG(e2.salary), 2)
FROM employees e2
WHERE e2.department_id = e.department_id
) AS dept_avg_salary
FROM employees e
ORDER BY e.department_id, e.name;การค้นหาพนักงานเงินเดือนสูงสุดของแต่ละแผนก
เราสามารถใช้คิวรีย่อยที่สัมพันธ์กันเพื่อค้นหาพนักงานที่มี เงินเดือนสูงสุดในแต่ละแผนกได้ คิวรีภายในจะค้นหาเงินเดือนสูงสุดของแผนกในแถวปัจจุบัน แล้วคิวรีภายนอกจะเก็บไว้เฉพาะแถวที่มีค่าตรงกัน
SELECT e1.name, e1.department_id, e1.salary
FROM employees e1
WHERE e1.salary = (
SELECT MAX(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
)
ORDER BY e1.department_id;EXISTS กับคิวรีย่อยที่สัมพันธ์กัน
ตัวดำเนินการ EXISTS มักใช้คู่กับคิวรีย่อยที่สัมพันธ์กัน โดยจะคืนค่า TRUE หากคิวรีภายในสร้างผลลัพธ์อย่างน้อยหนึ่งแถว ในที่นี้ เราจะแสดงแผนกทั้งหมดที่มีพนักงานอย่างน้อยหนึ่งคนซึ่งเข้าทำงานก่อนปี 2021
SELECT d.name AS department
FROM departments d
WHERE EXISTS (
SELECT 1
FROM employees e
WHERE e.department_id = d.id
AND e.hire_date < '2021-01-01'
);NOT EXISTS กับคิวรีย่อยที่สัมพันธ์กัน
NOT EXISTS มีความหมายตรงข้าม โดยจะคืนค่า TRUE เมื่อคิวรีย่อยที่สัมพันธ์กันไม่พบ แถวที่ตรงกัน เหมาะสำหรับค้นหาระเบียนแม่ที่ไม่มีระเบียนลูก เช่น แผนกที่ไม่มีพนักงาน
SELECT d.name AS department_without_employees
FROM departments d
WHERE NOT EXISTS (
SELECT 1
FROM employees e
WHERE e.department_id = d.id
);คิวรีย่อยที่สัมพันธ์กันใน UPDATE
คิวรีย่อยที่สัมพันธ์กันยังใช้ภายในคำสั่ง UPDATE ได้ด้วย ตัวอย่างต่อไปนี้จะเพิ่มคอลัมน์ dept_avg แล้วใช้คิวรีย่อยที่สัมพันธ์กันเติมเงินเดือนเฉลี่ยของแผนกให้กับพนักงานแต่ละคน
ALTER TABLE employees ADD COLUMN dept_avg NUMERIC(10,2);
UPDATE employees e1
SET dept_avg = (
SELECT ROUND(AVG(e2.salary), 2)
FROM employees e2
WHERE e2.department_id = e1.department_id
);
SELECT name, salary, dept_avg FROM employees ORDER BY department_id, name;คิวรีย่อยที่สัมพันธ์กันใน DELETE
คุณยังสามารถใช้คิวรีย่อยที่สัมพันธ์กันในคำสั่ง DELETE เพื่อลบแถวตามข้อมูลจากตารางที่เกี่ยวข้องได้ คิวรีด้านล่างจะลบพนักงานที่มีเงินเดือนต่ำกว่า 60% ของเงินเดือนเฉลี่ยในแผนก ซึ่งเป็นรูปแบบหนึ่งของการล้างข้อมูล
DELETE FROM employees e1
WHERE e1.salary < (
SELECT AVG(e2.salary) * 0.60
FROM employees e2
WHERE e2.department_id = e1.department_id
);
SELECT name, salary, department_id FROM employees ORDER BY department_id;เคล็ดลับด้านประสิทธิภาพ: คิวรีย่อยที่สัมพันธ์กันเปรียบเทียบกับ JOIN
คิวรีย่อยที่สัมพันธ์กันจะทำงานหนึ่งครั้งต่อแถวภายนอก จึงอาจช้าเมื่อตารางมีขนาดใหญ่ คิวรีย่อยที่สัมพันธ์กันจำนวนมากสามารถเขียนใหม่เป็น JOIN กับตารางที่สร้างจากคิวรีหรือ CTE เพื่อเพิ่มประสิทธิภาพได้ ควรทำความเข้าใจทั้งสองรูปแบบ แล้วเลือกใช้ตามความอ่านง่ายและแผนการทำงาน
-- Correlated version (potentially slower)
SELECT e1.name, e1.salary
FROM employees e1
WHERE e1.salary > (
SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
);
-- Equivalent JOIN + derived table (often faster)
SELECT e.name, e.salary
FROM employees e
JOIN (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
) dept_avg ON dept_avg.department_id = e.department_id
WHERE e.salary > dept_avg.avg_sal;ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับคิวรีย่อยที่สัมพันธ์กัน
สรุป: คิวรีย่อยที่สัมพันธ์กัน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า คิวรีย่อยที่สัมพันธ์กัน อ้างอิงคอลัมน์จากคิวรีภายนอกและถูกประเมินผลใหม่สำหรับแต่ละแถวภายนอก ประเด็นสำคัญ:
- คิวรีย่อยเหล่านี้ปรากฏได้ใน SELECT, WHERE, UPDATE และ DELETE
- EXISTS / NOT EXISTS ใช้คู่กับคิวรีย่อยที่สัมพันธ์กันได้อย่างเป็นธรรมชาติ เพื่อทดสอบว่ามีแถวที่เกี่ยวข้องหรือไม่
- คิวรีย่อยเหล่านี้สื่อความหมายได้ดี แต่อาจทำงานช้า ควรพิจารณาเขียนใหม่เป็น JOIN เมื่อประสิทธิภาพมีความสำคัญ
- นามแฝงของตารางภายนอกภายในคิวรีย่อยคือสิ่งที่ทำให้เกิดความสัมพันธ์
คำถามที่พบบ่อย
บทเรียน “คำค้นย่อยที่สัมพันธ์กัน” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คำค้นย่อยที่สัมพันธ์กัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คำค้นย่อยที่สัมพันธ์กัน”
คำค้นย่อยที่ขึ้นอยู่กับแถวภายนอก คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “คำค้นย่อยที่สัมพันธ์กัน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม
ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คำค้นย่อยที่สัมพันธ์กัน
- EXISTS และ NOT EXISTS
- IN เทียบกับ ANY เทียบกับ ALL
- ประสิทธิภาพของ EXISTS เทียบกับ JOIN