0Pricing
Coding Interview Prep · บทเรียน

ค่าสูงสุดอันดับที่ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เงินเดือนสูงสุดอันดับสอง ห้าวิธี
  2. ค่าสูงสุดอันดับที่ n ด้วย DENSE_RANK
  3. ผู้มีรายได้สูงสุดประจำแผนก
  4. ส่งคืน NULL เมื่อไม่มีค่าอันดับที่ n
← กลับไปที่ Coding Interview Prep