กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก
วิธีที่คิวรีภายในอ้างอิงแถวภายนอก และรูปแบบการทำงานทีละแถว
กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
อะไรทำให้ซับคิวรีมีความสัมพันธ์กับคิวรีภายนอก
ผู้สัมภาษณ์แบ่งซับคิวรีออกเป็นสองประเภท ซับคิวรีธรรมดา (ไม่สัมพันธ์กับคิวรีภายนอก) สามารถทำงานได้ด้วยตัวเอง ส่วนซับคิวรีแบบสัมพันธ์จะอ้างอิงคอลัมน์จากคิวรีภายนอก จึงไม่สามารถทำงานแบบแยกเดี่ยวได้
- แบบไม่สัมพันธ์: ประมวลผลครั้งเดียว แล้วนำผลลัพธ์กลับมาใช้กับทุกแถวภายนอก
- แบบสัมพันธ์: ประมวลผลใหม่หนึ่งครั้งต่อหนึ่งแถวภายนอก เพราะขึ้นอยู่กับแถวนั้น
สัญญาณที่บ่งชี้ได้ชัดเจนคือมีคอลัมน์จากตารางภายนอกปรากฏอยู่ภายในคิวรีภายใน เมื่อสังเกตเห็นสิ่งนี้ คุณก็ระบุรูปแบบได้ทันที
แบบจำลองการทำงานทีละแถว
ลองนึกภาพว่าระบบประมวลผลวนดูแถวภายนอก สำหรับแต่ละแถวภายนอก ระบบจะนำค่าของแถวนั้นไปใส่ในคิวรีภายใน เรียกใช้คิวรี แล้วใช้ผลลัพธ์เพื่อตัดสินใจหรือคำนวณบางอย่าง
นี่คือแบบจำลองทางความคิดที่ผู้สัมภาษณ์ต้องการให้คุณอธิบายเป็นคำพูด: "คิวรีภายในทำงานหนึ่งครั้งสำหรับทุกแถวภายนอก"
ถ้อยคำนี้ยังบอกเป็นนัยถึงคำถามต่อยอดแบบคลาสสิกด้วยว่า คิวรีย่อยแบบสัมพันธ์อาจทำงานช้า เพราะคิวรีภายในอาจทำงานหลายพันครั้ง เราจะแก้ปัญหานี้ในบทเรียนที่ 4
สังเกตการอ้างอิงแถวภายนอก
ในที่นี้ แถวพนักงานภายนอกที่ใช้นามแฝง e1 จะเป็นตัวขับคิวรีภายใน ซึ่งอ่านค่า e1.dept_id การอ้างอิงแถวภายนอกนี้คือความสัมพันธ์เชื่อมโยง
หากนำคำนำหน้านามแฝงออก คิวรีภายในจะคอมไพล์ด้วยตัวเองไม่ได้ การพึ่งพานี้เองที่ทำให้คิวรีเป็นคิวรีย่อยแบบสัมพันธ์
SELECT e1.name, e1.salary
FROM employees e1
WHERE e1.salary > (
SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.dept_id = e1.dept_id
);อ่านคิวรีนั้นออกเสียง
แปลคิวรีก่อนหน้าเป็นภาษาธรรมดาในแบบที่จะใช้อธิบายตอนสัมภาษณ์:
"สำหรับพนักงานแต่ละคน e1 ให้หาค่าเฉลี่ยเงินเดือนของแผนกของตนเอง แล้วเก็บพนักงานคนนั้นไว้เฉพาะเมื่อมีรายได้มากกว่าค่าเฉลี่ยของแผนก"
WHERE e2.dept_id = e1.dept_id ในคิวรีภายในทำให้ค่าเฉลี่ยผูกกับแผนกของพนักงานคนนี้ หากไม่มีบรรทัดนั้น คุณจะเปรียบเทียบทุกคนกับค่าเฉลี่ยของทั้งบริษัทแทน
ต้องใช้นามแฝง
เมื่อคิวรีภายในและคิวรีภายนอกแตะต้องตารางเดียวกัน คุณต้องกำหนดนามแฝงให้ทั้งคู่ เพื่อให้ระบบประมวลผลทราบว่าคอลัมน์นั้นเป็นของแถวใด
e1= แถวภายนอกที่กำลังถูกตรวจสอบe2= การอ่านตารางภายใน
หากตัดนามแฝงออก dept_id จะกำกวม ระบบประมวลผลหลายชนิดจะผูกคอลัมน์นี้กับตารางภายในโดยไม่แจ้งเตือน ทำให้ความสัมพันธ์เชื่อมโยงเสีย ผู้สัมภาษณ์มักจงใจวางกับดักด้วยข้อผิดพลาดนี้
คิวรีย่อยแบบสัมพันธ์ใน SELECT
คิวรีย่อยแบบสัมพันธ์ไม่ได้จำกัดอยู่แค่ใน WHERE ในรายการ SELECT คิวรีย่อยเหล่านี้จะสร้างคอลัมน์ที่คำนวณขึ้น และยังคงประเมินค่าแยกตามแถวภายนอก
ด้านล่าง คำสั่งซื้อแต่ละรายการจะแสดงว่าลูกค้าคนเดียวกันสั่งซื้อรายการอื่นกี่รายการ การนับภายในเชื่อมโยงกับแถวภายนอกผ่าน o.customer_id
SELECT o.order_id,
o.customer_id,
(SELECT COUNT(*)
FROM orders o2
WHERE o2.customer_id = o.customer_id) AS customer_order_count
FROM orders o;สเกลาร์หมายถึงค่าหนึ่งค่าเท่านั้น
คิวรีย่อยแบบสัมพันธ์ที่ใช้ใน SELECT หรือเปรียบเทียบด้วย =, >, < ต้องคืนค่าเดี่ยวเพียงค่าเดียวสำหรับแต่ละแถวภายนอก
หากคืนค่ามากกว่าหนึ่งแถว ฐานข้อมูลจะแจ้งข้อผิดพลาด เช่น "คิวรีย่อยคืนค่ามากกว่าหนึ่งแถว"
ฟังก์ชันรวมค่าอย่าง COUNT, MAX หรือ AVG รับประกันว่าจะได้ค่าเดียว จึงมักใช้ภายในคิวรีย่อยแบบสัมพันธ์ที่ต้องคืนค่าเดี่ยว การรู้กฎนี้จะช่วยป้องกันปัญหาที่เกิดขึ้นโดยไม่คาดคิดขณะทำงาน
เมื่อคิวรีย่อยคืนค่า NULL
คิวรีย่อยแบบสัมพันธ์ที่คืนค่าเดี่ยวอาจไม่พบแถวภายในเลยแม้แต่แถวเดียว ฟังก์ชันรวมค่าจะคืนค่า NULL (หรือคืนค่า 0 สำหรับ COUNT)
ค่า NULL นั้นจะถูกส่งต่อไปยังนิพจน์ภายนอก การเปรียบเทียบกับ NULL จะให้ผลเป็น UNKNOWN ดังนั้นแถวภายนอกอาจถูกตัดออกโดยไม่แจ้งเตือน
หากต้องการค่าทดแทน ให้ครอบคิวรีย่อยด้วย COALESCE ผู้สัมภาษณ์มักถามว่าเกิดอะไรขึ้นเมื่อไม่พบแถวภายใน โดยคาดหวังให้คุณอธิบายพฤติกรรมของ NULL
SELECT c.customer_id,
COALESCE((SELECT MAX(o.amount)
FROM orders o
WHERE o.customer_id = c.customer_id), 0) AS biggest_order
FROM customers c;ตัวอย่างพร้อมวิธีทำ: วันที่สั่งซื้อล่าสุด
งานที่พบบ่อยคือแสดงลูกค้าแต่ละรายพร้อมวันที่สั่งซื้อล่าสุดของลูกค้ารายนั้น คิวรีย่อยแบบสัมพันธ์ใน SELECT ทำงานนี้ได้โดยตรง
สำหรับแถวลูกค้าแต่ละแถว คิวรีภายในจะหาวันที่สั่งซื้อสูงสุดด้วย MAX สำหรับลูกค้ารายนั้นผ่าน o.customer_id = c.customer_id
SELECT c.customer_id,
c.name,
(SELECT MAX(o.order_date)
FROM orders o
WHERE o.customer_id = c.customer_id) AS last_order_date
FROM customers c;เหตุใดจึงอาจทำงานช้า
เนื่องจากคิวรีภายในทำงานหนึ่งครั้งต่อแถวภายนอก คิวรีย่อยแบบสัมพันธ์ที่ทำงานกับตารางภายนอกขนาดใหญ่อาจทำให้เกิดการทำงานภายในนับล้านครั้ง
- ดัชนีบนคอลัมน์ที่ใช้เชื่อมโยง (ในที่นี้คือ
orders.customer_id) ช่วยให้การทำงานภายในแต่ละครั้งเสร็จได้อย่างรวดเร็ว - หากไม่มีดัชนี การทำงานแต่ละครั้งอาจต้องอ่านทั้งตาราง ทำให้มีงานโดยประมาณระดับ O(n*m)
ในการสัมภาษณ์ ให้กล่าวถึงดัชนีและการเขียนใหม่เป็นการเชื่อมตารางเสมอ เพราะเป็นปัจจัยสำคัญที่ใช้ควบคุมประสิทธิภาพ
เปรียบเทียบคิวรีย่อยแบบสัมพันธ์กับแบบไม่สัมพันธ์
ความแตกต่างอยู่ที่บรรทัดเดียว แบบไม่สัมพันธ์จะเปรียบเทียบทุกคนกับค่าเฉลี่ยของทั้งบริษัท ส่วนแบบสัมพันธ์จะเปรียบเทียบแต่ละคนกับแผนกของตนเอง
อ่านทั้งสองแบบและสังเกตว่าบรรทัด WHERE e2.dept_id = e1.dept_id เพียงบรรทัดเดียวเปลี่ยนความหมายทั้งหมดอย่างไร
-- Uncorrelated: one global average, computed once
SELECT name FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- Correlated: per-department average, recomputed per row
SELECT e1.name FROM employees e1
WHERE e1.salary > (
SELECT AVG(e2.salary) FROM employees e2
WHERE e2.dept_id = e1.dept_id
);ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับสิ่งที่กำหนดคิวรีย่อยแบบสัมพันธ์
สรุป: องค์ประกอบของคิวรีย่อยแบบสัมพันธ์
ประเด็นสำคัญ:
- คิวรีย่อยแบบสัมพันธ์อ้างอิงแถวภายนอกและทำงานหนึ่งครั้งต่อแถวภายนอก
- กำหนดนามแฝงให้ทั้งสองตารางเมื่อเป็นตารางเดียวกัน เพื่อให้ความสัมพันธ์เชื่อมโยงไม่กำกวม
- การใช้งานแบบค่าเดี่ยวต้องคืนค่าหนึ่งค่าเท่านั้น หากไม่พบข้อมูลจะได้ค่า NULL จึงควรป้องกันด้วย
COALESCE - คิวรีย่อยสามารถอยู่ใน SELECT หรือ WHERE ได้ และประสิทธิภาพขึ้นอยู่กับการสร้างดัชนีบนคอลัมน์ที่ใช้เชื่อมโยง
พูดว่า "ทำงานหนึ่งครั้งต่อแถวภายนอก" ในการสัมภาษณ์ แล้วคุณก็แสดงให้เห็นว่าเข้าใจแนวคิดหลักอย่างถ่องแท้
คำถามที่พบบ่อย
บทเรียน “กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก”
วิธีที่คิวรีภายในอ้างอิงแถวภายนอก และรูปแบบการทำงานทีละแถว คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม
ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- กายวิภาคของคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอก
- ฟังก์ชันรวมแยกตามกลุ่มโดยไม่มี GROUP BY
- EXISTS และ NOT EXISTS ที่สัมพันธ์กับคิวรีภายนอก
- เขียนคิวรีย่อยที่สัมพันธ์กับคิวรีภายนอกใหม่เป็นการเชื่อมตาราง