ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK
ขยายแนวคิดไปสู่ค่าที่แตกต่างกันอันดับที่ n และจัดการค่าซ้ำ
ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
การต่อยอดไปสู่เงินเดือนสูงสุดลำดับที่ N
เมื่อคุณค้นหาเงินเดือนสูงสุดลำดับที่สองได้แล้ว ผู้สัมภาษณ์มักถามต่อทันทีว่า "ถ้าเป็นเงินเดือนสูงสุดลำดับที่ N ล่ะ" คำตอบที่ตรงไปตรงมาและอธิบายได้ดีที่สุดคือการใช้ DENSE_RANK
รูปแบบจะเหมือนเดิมเสมอ: จัดอันดับเงินเดือนที่ไม่ซ้ำกันจากมากไปน้อย จากนั้นกรองหาแถวที่มีอันดับเท่ากับ N เนื่องจากตรรกะไม่เปลี่ยนแปลงตามค่า N วิธีเดียวนี้จึงตอบคำถามในกลุ่มนี้ได้ทั้งหมด
เราจะสร้างวิธีนี้ทีละขั้น จัดการค่าที่เท่ากันและค่าซ้ำ และอธิบายว่าเหตุใด DENSE_RANK จึงเป็นฟังก์ชันจัดอันดับที่เหมาะสมกับความหมายแบบ "ค่าที่ไม่ซ้ำกัน"
แม่แบบหลัก
นี่คือแม่แบบที่นำกลับมาใช้ซ้ำได้สำหรับเงินเดือนสูงสุดลำดับที่ N ให้แทนค่าคงที่ด้วยค่า N ที่ผู้สัมภาษณ์ถาม
คุณคำนวณ DENSE_RANK ในคิวรีภายใน เนื่องจากฟังก์ชันหน้าต่างไม่สามารถอยู่ใน WHERE ได้ จากนั้นกรองด้วย rnk = N ในคิวรีภายนอก สำหรับเงินเดือนสูงสุดลำดับที่ 3 ให้กำหนดตัวกรองเป็น rnk = 3
SELECT salary AS nth_highest
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) ranked
WHERE rnk = 3;วิธีที่ DENSE_RANK กำหนดหมายเลขให้ค่าที่ไม่ซ้ำกัน
DENSE_RANK กำหนดอันดับเดียวกันให้ค่าที่เท่ากัน และไม่เว้นลำดับหลังจากนั้นเลย ซึ่งตรงกับนิยามของ "ค่าที่ไม่ซ้ำกันลำดับที่ N" ที่ผู้สัมภาษณ์ต้องการพอดี
สำหรับเงินเดือน 800, 800, 600, 600, 400:
- 800 -> อันดับ 1
- 600 -> อันดับ 2
- 400 -> อันดับ 3
ดังนั้นเงินเดือนสูงสุดลำดับที่ 3 คือ 400 แม้ว่าจะมีอยู่ห้าแถว ค่าซ้ำจะถูกรวมเป็นอันดับเดียวโดยอัตโนมัติ
เหตุใด RANK จึงให้คำตอบผิด
หากเปลี่ยนเป็น RANK คำตอบจะผิด RANK เว้นลำดับตามจำนวนค่าที่เท่ากัน
สำหรับ 800, 800, 600, 600, 400:
- 800, 800 -> อันดับ 1 (มีสองแถว)
- 600, 600 -> อันดับ 3 (มีการเว้นลำดับ จึงไม่มีอันดับ 2)
- 400 -> อันดับ 5
การกรองด้วย rnk = 3 จะส่งคืน 600 และ rnk = 2 จะไม่ส่งคืนอะไรเลย หากผู้สัมภาษณ์ไม่ได้ต้องการการจัดอันดับแบบแข่งขันโดยเฉพาะ DENSE_RANK คือคำตอบที่ถูกต้องสำหรับ "เงินเดือนที่ไม่ซ้ำกันลำดับที่ N"
เหตุใด ROW_NUMBER ก็ไม่ถูกต้องในกรณีนี้
ROW_NUMBER กำหนดหมายเลขไม่ซ้ำกันให้ทุกแถว โดยไม่สนใจค่าที่เท่ากันเลย สำหรับ 800, 800, 600, 600, 400 จะได้ 1, 2, 3, 4, 5
ดังนั้น rn = 3 จะส่งคืน 600 แต่ rn = 2 จะส่งคืน 800 ที่ซ้ำกัน ไม่ใช่ค่าที่สองซึ่งไม่ซ้ำกัน ROW_NUMBER ตอบคำถามว่า "แถวที่ N" ไม่ใช่ "ค่าที่ไม่ซ้ำกันลำดับที่ N"
ใช้ ROW_NUMBER เฉพาะเมื่อคำถามต้องการแถวใดแถวหนึ่งจริง ๆ เช่น การลบค่าซ้ำ หรือการเลือก N อันดับแรกต่อกลุ่มโดยเก็บไว้เพียงแถวเดียว
SELECT salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM employee;การกำหนด N เป็นพารามิเตอร์อย่างปลอดภัย
ในโค้ดจริง คุณไม่ควรกำหนดอันดับตายตัว ให้ส่ง N เป็นพารามิเตอร์แล้วนำมาเปรียบเทียบ นิยามฟังก์ชันหน้าต่างยังคงเหมือนเดิม มีเพียงตัวกรองภายนอกเท่านั้นที่กำหนดเป็นพารามิเตอร์
จุดนี้ยังช่วยให้คุณส่งคืนเงินเดือนที่เสมอกันทั้งหมดในอันดับ N ได้ด้วย เนื่องจาก DENSE_RANK ใช้อันดับเดียวกันกับค่าที่เสมอกัน WHERE rnk = N จึงอาจส่งคืนหลายแถว หากพนักงานหลายคนมีเงินเดือนที่ไม่ซ้ำกันลำดับที่ N ซึ่งมักเป็นพฤติกรรมที่ต้องการ
SELECT id, salary
FROM (
SELECT id, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) ranked
WHERE rnk = :n;การต่อยอดการนับแบบสัมพันธ์
แนวทางก่อนมีฟังก์ชันหน้าต่างก็ต่อยอดได้เช่นกัน: เงินเดือนจะเป็นเงินเดือนสูงสุดลำดับที่ N ที่ไม่ซ้ำกัน เมื่อมีเงินเดือนที่ไม่ซ้ำกันและสูงกว่าค่านั้นอย่างเคร่งครัดอยู่พอดี N - 1 ค่า
สำหรับเงินเดือนสูงสุดลำดับที่ 3 ให้กำหนดว่าต้องมีเงินเดือนที่สูงกว่าและไม่ซ้ำกันอยู่พอดี 2 ค่า วิธีนี้ใช้ได้กับระบบรุ่นเก่าที่ไม่มีฟังก์ชันหน้าต่าง แต่รองรับข้อมูลขนาดใหญ่ได้ไม่ดี เพราะการนับภายในจะทำงานซ้ำสำหรับแต่ละแถวภายนอก
SELECT DISTINCT salary AS nth_highest
FROM employee e
WHERE (
SELECT COUNT(DISTINCT e2.salary)
FROM employee e2
WHERE e2.salary > e.salary
) = 2;รูปแบบฟังก์ชัน MySQL ที่ผู้สัมภาษณ์มักขอ
โจทย์ "เงินเดือนสูงสุดลำดับที่ N" แบบ LeetCode มักขอให้เขียนฟังก์ชันที่จัดเก็บไว้เพื่อส่งคืนค่าเดียว เนื้อหาของฟังก์ชันคือแม่แบบ DENSE_RANK ที่ครอบไว้เพื่อส่งคืนเงินเดือนหนึ่งค่า
คุณไม่จำเป็นต้องท่องจำไวยากรณ์ฟังก์ชันที่แน่นอนในการสัมภาษณ์ แต่ควรรู้จักสำนวนย่อของ MySQL อย่าง LIMIT N-1, 1 ที่ใช้กับเงินเดือนที่ไม่ซ้ำกัน
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 2; -- N = 3, so OFFSET N-1ตัวอย่าง: เงินเดือนสูงสุดลำดับที่ 4
เงินเดือน: 1000, 900, 900, 700, 500, 500, 300
ค่าที่ไม่ซ้ำกันเรียงจากมากไปน้อยด้วย DENSE_RANK:
- 1000 -> 1
- 900 -> 2
- 700 -> 3
- 500 -> 4
- 300 -> 5
เงินเดือนสูงสุดลำดับที่ 4 คือ 500 โปรดสังเกตว่าแถวของ 500 ทั้งสองแถวใช้อันดับ 4 ร่วมกัน ดังนั้นการกรองด้วย rnk = 4 จะส่งคืนพนักงานทั้งสองคนที่ได้เงินเดือน 500 หากคุณเลือกดูรหัสของพวกเขาด้วย
ข้อสังเกตด้านประสิทธิภาพ
เมื่อข้อมูลมีขนาดใหญ่ วิธีต่าง ๆ เปรียบเทียบกันอย่างไร
- DENSE_RANK: เรียงข้อมูลหนึ่งครั้ง แล้วจึงกรอง มีประสิทธิภาพ และตัววางแผนคิวรีสามารถใช้ดัชนีในคอลัมน์เงินเดือนเพื่อการเรียงลำดับได้
- การนับแบบสัมพันธ์: อาจมีความซับซ้อนเป็น O(n²) เพราะฟังก์ชันรวมภายในทำงานซ้ำสำหรับแต่ละแถว ควรหลีกเลี่ยงกับตารางขนาดใหญ่
- LIMIT/OFFSET: ทำงานเร็วเมื่อ N มีค่าน้อย แต่ยังต้องเรียงข้อมูล และค่าออฟเซ็ตขนาดใหญ่จะต้องสแกนแล้วทิ้งหลายแถว
เริ่มต้นด้วย DENSE_RANK แล้วแทบไม่มีทางตอบผิด
กรณีขอบที่ควรกล่าวถึง
ผู้สมัครที่มีความสามารถจะกล่าวถึงกรณีขอบเหล่านี้ก่อนที่จะถูกถาม:
- N มากกว่าจำนวนเงินเดือนที่ไม่ซ้ำกัน: ตัวกรองจะไม่ตรงกับแถวใดและส่งคืนผลลัพธ์ว่าง บทเรียนที่ 4 จะอธิบายวิธีบังคับให้ส่งคืน NULL เพียงค่าเดียว
- ค่าที่เท่ากันในอันดับ N: DENSE_RANK จะส่งคืนพนักงานทุกคนที่มีอันดับเท่ากัน คุณต้องตัดสินใจว่าต้องการพฤติกรรมนี้หรือไม่
- N = 1: แม่แบบยังคงใช้ได้และส่งคืนค่าสูงสุด
ตรวจสอบความเข้าใจ
ลองใช้แม่แบบเงินเดือนสูงสุดลำดับที่ N
สรุป
คำตอบมาตรฐานสำหรับเงินเดือนสูงสุดลำดับที่ N คือ จัดอันดับเงินเดือนที่ไม่ซ้ำกันด้วย DENSE_RANK() OVER (ORDER BY salary DESC) ในคิวรีย่อย แล้วกรองด้วย WHERE rnk = N
- DENSE_RANK หมายถึง "ค่าที่ไม่ซ้ำกันลำดับที่ N" โดยค่าที่เท่ากันใช้อันดับร่วมกันและไม่มีการเว้นลำดับ
- RANK ทำให้เกิดการเว้นลำดับ ส่วน ROW_NUMBER นับแถว ไม่ใช่ค่า
- เทคนิคการนับแบบสัมพันธ์ = N-1 ใช้แนวคิดเดียวกันโดยไม่ใช้ฟังก์ชันหน้าต่าง แต่รองรับข้อมูลขนาดใหญ่ได้ไม่ดี
โปรดระบุกรณีขอบที่ "N มากกว่าจำนวนค่าที่มีอยู่" เสมอ ซึ่งเราจะแก้ไขในหัวข้อถัดไป
คำถามที่พบบ่อย
บทเรียน “ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK”
ขยายแนวคิดไปสู่ค่าที่แตกต่างกันอันดับที่ n และจัดการค่าซ้ำ คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม
ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เงินเดือนสูงสุดอันดับสอง ห้าวิธี
- ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK
- ผู้มีรายได้สูงสุดประจำแผนก
- ส่งคืน NULL เมื่อไม่มีค่าอันดับที่ n