ค้นหาช่องว่างในลำดับ
ตรวจจับค่าที่หายไป รวมถึงจุดเริ่มต้นและจุดสิ้นสุดของแต่ละช่องว่าง
ค้นหาช่องว่างในลำดับ เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
ตอนนี้มาค้นหาช่องว่าง
จนถึงตอนนี้ เราจัดกลุ่มแถวให้เป็นช่วงต่อเนื่องแล้ว คำถามสัมภาษณ์ที่เป็นภาพกลับด้านคือ ค่าใดหายไปบ้าง? ผู้สัมภาษณ์อาจถามว่า ให้หาช่องว่างในลำดับ ID, หมายเลขใบแจ้งหนี้ใดถูกข้ามไป หรือวันใดไม่มีการดำเนินการ
ช่องว่างคือพื้นที่ว่างระหว่างช่วงต่อเนื่อง ประเด็นสำคัญคือ โดยทั่วไปคุณไม่จำเป็นต้องแสดงค่าที่หายไปทุกค่า แต่ควรรายงาน จุดเริ่มต้นและจุดสิ้นสุดของช่วงช่องว่างแต่ละช่วง ซึ่งกระชับกว่ามากและเป็นสิ่งที่ผู้สัมภาษณ์คาดหวัง
ชุดข้อมูลตัวอย่างช่องว่าง
นำค่าที่มีอยู่ 1, 2, 3, 7, 8, 10 จากตาราง seq(n) กลับมาใช้ ช่องว่างที่ต้องรายงานคือ:
- ตั้งแต่ 4 ถึง 6 (หลังช่วงต่อเนื่องแรกและก่อน 7)
- ตั้งแต่ 9 ถึง 9 (ระหว่าง 8 กับ 10)
สังเกตว่าเราอธิบายช่องว่างเป็น ช่วง: จุดเริ่มต้นของช่องว่าง = ค่าสุดท้ายที่มีอยู่ + 1, จุดสิ้นสุดของช่องว่าง = ค่าถัดไป - 1 รูปแบบที่กระชับนี้คือเป้าหมายของเทคนิคหลักด้านล่าง
CREATE TABLE seq (n INT);
INSERT INTO seq VALUES (1),(2),(3),(7),(8),(10);แนวทางใช้ LEAD เพื่อหาช่องว่าง
ตัวตรวจจับช่องว่างที่สะอาดที่สุดคือการเปรียบเทียบแต่ละแถวกับแถว ถัดไป โดยใช้ LEAD หากค่าถัดไปมากกว่าค่าปัจจุบันเกิน 1 ก็แสดงว่ามีช่องว่างระหว่างสองค่านี้
สำหรับแต่ละแถวดังกล่าว ช่องว่างจะเริ่มที่ n + 1 และสิ้นสุดที่ next_n - 1 ลองดูผลลัพธ์ดิบจาก LEAD ก่อน:
SELECT
n,
LEAD(n) OVER (ORDER BY n) AS next_n
FROM seq
ORDER BY n;รายงานช่วงช่องว่าง
นำผลลัพธ์จาก LEAD ใส่ไว้ใน CTE แล้วเก็บเฉพาะแถวที่การกระโดดไปยังค่าถัดไปมากกว่า 1 แถวดังกล่าวเป็นตัวระบุช่องว่าง:
ผลลัพธ์นี้คืนค่าช่องว่าง 4-6 และช่องว่าง 9-9 ได้ตรงตามต้องการ นิพจน์ next_n - n - 1 ยังให้จำนวนค่าที่หายไปในแต่ละช่องว่างด้วย ซึ่งเป็นคำถามต่อยอดที่พบบ่อย
WITH stepped AS (
SELECT n, LEAD(n) OVER (ORDER BY n) AS next_n
FROM seq
)
SELECT
n + 1 AS gap_start,
next_n - 1 AS gap_end,
next_n - n - 1 AS missing_count
FROM stepped
WHERE next_n - n > 1
ORDER BY gap_start;รูปแบบสมมาตรที่ใช้ LAG
คุณสามารถตรวจจับช่องว่างเดียวกันได้โดยมอง ย้อนกลับ ด้วย LAG แทน ช่องว่างจะมีอยู่ก่อนแถวปัจจุบัน เมื่อค่าก่อนหน้าต่ำกว่าค่าปัจจุบันมากกว่า 1
สองวิธีนี้ให้ผลเหมือนกันทั้งหมด ให้เลือกวิธีที่อ่านเป็นธรรมชาติกว่าสำหรับคำถามนั้น ผู้สัมภาษณ์บางคนชอบ LEAD เพราะอธิบายช่องว่างโดยอ้างอิงจากแถวที่อยู่ก่อนหน้า ซึ่งสอดคล้องกับวิธีที่คนทั่วไปพูด
WITH stepped AS (
SELECT n, LAG(n) OVER (ORDER BY n) AS prev_n
FROM seq
)
SELECT prev_n + 1 AS gap_start,
n - 1 AS gap_end
FROM stepped
WHERE n - prev_n > 1
ORDER BY gap_start;แสดงค่าที่หายไปทุกค่า
บางครั้งผู้สัมภาษณ์ต้องการรายการตัวเลขที่หายไปทั้งหมดจริง ๆ ไม่ใช่เพียงช่วง วิธีที่รัดกุมคือสร้าง ลำดับที่คาดหมายให้ครบถ้วน แล้วเชื่อมกับข้อมูลที่มีอยู่เพื่อคัดรายการที่ไม่พบ ในโพสต์เกรส generate_series ใช้สร้างช่วงทั้งหมด:
จำนวนเต็มทุกค่าภายในช่วงที่คาดหมายซึ่งไม่ปรากฏใน seq คือค่าที่หายไป วิธีนี้ยังรองรับช่องว่างที่ขอบช่วงทั้งสองด้าน หากคุณทราบค่าต่ำสุดและค่าสูงสุดที่ควรมี
SELECT g.n AS missing_value
FROM generate_series(
(SELECT MIN(n) FROM seq),
(SELECT MAX(n) FROM seq)
) AS g(n)
LEFT JOIN seq s ON s.n = g.n
WHERE s.n IS NULL
ORDER BY g.n;การสร้างลำดับข้ามระบบ
ไม่ใช่ทุกระบบจะมี generate_series คุณควรรู้จักทางเลือกอื่น:
- โพสต์เกรส:
generate_series(1, 100) - เซิร์ฟเวอร์เอสคิวแอล: CTE แบบเรียกซ้ำ หรือตารางตัวเลข/ตารางนับ
- MySQL 8: CTE แบบเรียกซ้ำที่นับขึ้นไปจนถึงค่าสูงสุด
CTE แบบเรียกซ้ำเป็นทางเลือกสำรองที่ใช้ได้ข้ามระบบ โดยจะสร้างลำดับที่คาดหมายแบบเดียวกันเพื่อเชื่อมคัดรายการที่ไม่พบ
WITH RECURSIVE nums AS (
SELECT (SELECT MIN(n) FROM seq) AS n
UNION ALL
SELECT n + 1 FROM nums
WHERE n + 1 <= (SELECT MAX(n) FROM seq)
)
SELECT nums.n AS missing_value
FROM nums
LEFT JOIN seq s ON s.n = nums.n
WHERE s.n IS NULL;ช่องว่างในวันที่ตามปฏิทิน
สำหรับวันที่ที่หายไป ให้สร้างปฏิทินเต็มรูปแบบโดยเพิ่มทีละวัน แล้วเชื่อมเพื่อคัดวันที่ที่ไม่มีข้อมูลออกมา นี่คือคำสั่งมาตรฐานสำหรับค้นหาวันที่ไม่มีรายการสั่งซื้อ:
ผสานวิธีนี้กับเทคนิคการหาช่วง โดยใช้ LEAD กับวันที่ที่มีอยู่จริง เพื่อรายงาน ช่วงวันที่ ที่หายไปแทนการแสดงทีละวัน และใช้ + INTERVAL '1 day' กำหนดขอบเขต
SELECT d::date AS missing_day
FROM generate_series(
DATE '2026-01-01', DATE '2026-01-31',
INTERVAL '1 day') AS d
LEFT JOIN daily_logins l ON l.login_date = d::date
WHERE l.login_date IS NULL
ORDER BY missing_day;ช่องว่างที่อยู่นอกขอบเขตข้อมูล
ข้อผิดพลาดที่สังเกตได้ยากคือ LEAD/LAG จะค้นพบเฉพาะช่องว่าง ระหว่างค่าที่มีอยู่เท่านั้น หากมีค่าหายไปก่อนค่าต่ำสุดหรือหลังค่าสูงสุดที่มีอยู่ วิธีใช้ฟังก์ชันหน้าต่างจะมองไม่เห็น เพราะไม่มีแถวข้างเคียง
หากผู้สัมภาษณ์กำหนดช่วงเต็มที่ควรมี เช่น ID ตั้งแต่ 1 ถึง 100 และข้อมูลของคุณเริ่มที่ 5 คุณต้องใช้วิธีสร้างลำดับแล้วเชื่อมเพื่อคัดรายการที่ไม่พบ โดยกำหนดขอบเขตตามช่วงที่ประกาศ ไม่ใช่ใช้ค่าต่ำสุดและค่าสูงสุดของข้อมูลเอง ควรยืนยันเสมอว่าขอบเขตที่คาดหมายถูกกำหนดตายตัวหรือไม่
SELECT g.n AS missing_value
FROM generate_series(1, 100) AS g(n)
LEFT JOIN seq s ON s.n = g.n
WHERE s.n IS NULL;การตรวจจับช่องว่างแยกตามกลุ่ม
สำหรับช่องว่างแยกตามผู้ใช้ ให้แบ่งการคำนวณ LEAD/LAG ตามคอลัมน์กลุ่ม เพื่อไม่ให้รายงานช่องว่างข้ามกระแสข้อมูลของผู้ใช้สองคน:
ช่วงที่หายไปของผู้ใช้แต่ละคนจะถูกคำนวณแยกจากกัน เช่นเดียวกับช่วงต่อเนื่อง การลืมแบ่งส่วนจะทำให้ผู้ใช้ถูกรวมกันโดยไม่มีสัญญาณเตือน และสร้างช่องว่างลวงที่พาดผ่านแถวซึ่งไม่เกี่ยวข้องกัน
WITH stepped AS (
SELECT user_id, n,
LEAD(n) OVER (PARTITION BY user_id ORDER BY n) AS next_n
FROM seq_per_user
)
SELECT user_id, n + 1 AS gap_start, next_n - 1 AS gap_end
FROM stepped
WHERE next_n - n > 1
ORDER BY user_id, gap_start;เลือกวิธีหาช่องว่างให้เหมาะสม
แนวทางตัดสินใจสำหรับการสัมภาษณ์:
- ต้องการช่วงแบบกระชับ และสนใจเฉพาะช่องว่างภายในหรือไม่ ให้ใช้
LEAD/LAGแล้วกรองแถวที่ขั้นมากกว่า 1 - ต้องการค่าที่หายไปทีละค่า หรือช่องว่างที่อยู่นอกขอบเขตข้อมูลหรือไม่ ให้ใช้ การสร้างลำดับแล้วเชื่อมเพื่อคัดรายการที่ไม่พบ กับช่วงเต็มที่ประกาศไว้
การกล่าวถึงทั้งสองทางเลือกและอธิบายว่าแต่ละแบบเหมาะกับกรณีใดแสดงให้เห็นถึงความเข้าใจอย่างลึกซึ้ง วิธี LEAD ใช้ทรัพยากรน้อยกว่า ส่วนวิธีสร้างลำดับครอบคลุมกว่า
ตรวจสอบความเข้าใจ
ทำความเข้าใจกับข้อผิดพลาดที่ขอบเขตให้ชัดเจน
ทบทวน: การค้นหาช่องว่าง
สรุปการตรวจจับช่องว่าง:
- รายงานช่องว่างเป็น ช่วง: จุดเริ่มต้นของช่องว่าง = ค่า + 1, จุดสิ้นสุดของช่องว่าง = ค่าถัดไป - 1
- ใช้
LEAD(หรือLAGแบบสมมาตร) แล้วกรองแถวที่ขั้นมากกว่า 1 เพื่อค้นหาช่องว่างภายในได้อย่างประหยัด - การสร้างลำดับแล้วเชื่อมเพื่อคัดรายการที่ไม่พบ จะแสดงค่าที่หายไปทุกค่า และตรวจจับช่องว่างที่ขอบเขตได้เมื่อเทียบกับช่วงที่ประกาศไว้
- ใช้ CTE แบบเรียกซ้ำสร้างลำดับในระบบที่ไม่มี
generate_series - แบ่งส่วนตามคอลัมน์กลุ่มสำหรับการค้นหาช่องว่างแยกตามผู้ใช้
- ยืนยันขอบเขตที่คาดหมายให้ชัดเจนเสมอ
สุดท้าย เราจะจัดการรูปแบบที่มีรายละเอียดมากที่สุด นั่นคือช่วงต่อเนื่องที่กำหนดโดยวันที่และการเปลี่ยนแปลงสถานะ
คำถามที่พบบ่อย
บทเรียน “ค้นหาช่องว่างในลำดับ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ค้นหาช่องว่างในลำดับ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ค้นหาช่องว่างในลำดับ”
ตรวจจับค่าที่หายไป รวมถึงจุดเริ่มต้นและจุดสิ้นสุดของแต่ละช่องว่าง คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ค้นหาช่องว่างในลำดับ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม
ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- รู้จักโจทย์ช่องว่างและกลุ่มต่อเนื่อง
- เทคนิคผลต่างของหมายเลขแถว
- ค้นหาช่องว่างในลำดับ
- กลุ่มต่อเนื่องเมื่อวันที่และสถานะเปลี่ยนแปลง