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

RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน

คำถามคลาสสิกเรื่องการจัดอันดับที่มีช่องว่างกับไม่มีช่องว่างเมื่อค่าซ้ำกัน

RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

ฟังก์ชันจัดอันดับสามแบบเปรียบเทียบกัน

SQL มีฟังก์ชันหน้าต่างสำหรับจัดอันดับสามแบบ และคำถามเกี่ยวกับหน้าต่างที่ถูกถามมากที่สุดข้อหนึ่งคือ ฟังก์ชันเหล่านี้แตกต่างกันอย่างไรเมื่อค่ากัน:

  • ROW_NUMBER — ไม่ซ้ำกันเสมอ ค่าที่เท่ากันจะได้หมายเลขที่แตกต่างกันแบบไม่แน่นอน
  • RANK — ค่าที่เท่ากันใช้อันดับเดียวกัน จากนั้นอันดับถัดไปจะข้ามหมายเลขและเกิดช่องว่าง
  • DENSE_RANK — ค่าที่เท่ากันใช้อันดับเดียวกัน จากนั้นอันดับถัดไปจะไม่ข้ามหมายเลขและไม่มีช่องว่าง

การอธิบายความแตกต่างนี้ได้ทันทีเป็นสัญญาณที่ดีในการสัมภาษณ์

ตารางตัวอย่างที่เห็นภาพชัดเจน

ลองนึกถึงคะแนนห้าค่าที่เรียงจากมากไปน้อย: 100, 90, 90, 80, 70 แล้วดูว่าฟังก์ชันแต่ละตัวกำหนดหมายเลขอย่างไร

  • ROW_NUMBER: 1, 2, 3, 4, 5
  • RANK: 1, 2, 2, 4, 5 (ข้าม 3 หลังค่าที่เท่ากัน)
  • DENSE_RANK: 1, 2, 2, 3, 4 (ไม่ข้ามหมายเลข)

จดจำตัวอย่าง 100/90/90/80/70 นี้ไว้ เพราะจะช่วยตอบคำถามได้ทันที

SELECT
  score,
  ROW_NUMBER()  OVER (ORDER BY score DESC) AS rownum,
  RANK()        OVER (ORDER BY score DESC) AS rnk,
  DENSE_RANK()  OVER (ORDER BY score DESC) AS dense
FROM scores;

วิธีที่ RANK คำนวณช่องว่าง

RANK กำหนดอันดับให้แต่ละแถวเท่ากับหนึ่งบวกจำนวนแถวที่อยู่ก่อนหน้าแถวนั้นอย่างชัดเจนตามลำดับที่กำหนด แถวสองแถวที่มีค่า 90 เท่ากันต่างก็มีแถวหนึ่งแถว (100) อยู่ก่อนหน้า จึงได้อันดับ 2 ทั้งคู่ ส่วนค่าถัดไปที่ต่ำกว่าจะมีสามแถวอยู่ก่อนหน้า จึงกระโดดไปเป็นอันดับ 4

นี่คือเหตุผลที่ RANK สอดคล้องกับการให้คะแนนการแข่งขัน ผู้ได้เหรียญเงินที่คะแนนเท่ากันจะมีอันดับเดียวกัน จึงไม่มีผู้ได้เหรียญทองแดง

-- scores 100,90,90,80 -> RANK = 1,2,2,4
SELECT score, RANK() OVER (ORDER BY score DESC) AS rnk
FROM scores;

วิธีที่ DENSE_RANK หลีกเลี่ยงช่องว่าง

DENSE_RANK กำหนดอันดับให้เท่ากับหนึ่งบวกจำนวนค่าที่แตกต่างกันซึ่งอยู่ก่อนหน้าค่าปัจจุบัน หลังจากค่าที่ 90 เท่ากัน มีค่าที่แตกต่างกันเพียงสองค่าอยู่ก่อนหน้า 80 คือ 100 และ 90 ดังนั้น 80 จึงได้อันดับ 3 โดยไม่มีช่องว่าง

ใช้ DENSE_RANK เมื่อสนใจตำแหน่งของค่าที่ไม่ซ้ำกัน เช่น "เงินเดือนสูงเป็นอันดับสอง" โดยต้องนับค่าที่เท่ากันเป็นหนึ่งค่า

-- scores 100,90,90,80 -> DENSE_RANK = 1,2,2,3
SELECT score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense
FROM scores;

เมื่อใดควรเลือกใช้แต่ละฟังก์ชัน

คู่มือช่วยตัดสินใจสั้น ๆ ที่ผู้สัมภาษณ์ชอบให้ผู้สมัครอธิบาย:

  • ต้องการหนึ่งแถวพอดีต่อแต่ละตำแหน่ง (ระเบียนล่าสุด การแบ่งหน้า)? → ROW_NUMBER
  • ต้องการอันดับที่ผู้ได้คะแนนเท่ากันอยู่ในอันดับเดียวกัน และมีช่องว่างของอันดับถูกต้อง (อันดับกีฬา อันดับ 3 อันดับแรกโดยรวมผู้ที่ได้คะแนนเท่ากัน)? → RANK
  • ต้องการค่าที่ไม่ซ้ำกันลำดับที่ N (เงินเดือนสูงสุดลำดับที่ N)? → DENSE_RANK

การเลือกผิดจะเปลี่ยนแถวที่คิวรีส่งกลับ ดังนั้นโปรดอธิบายเหตุผลของการเลือกให้ฟังอย่างชัดเจน

การจัดอันดับภายในแต่ละพาร์ติชัน

ฟังก์ชันทั้งสามรับ PARTITION BY เพื่อจัดอันดับแยกกันภายในแต่ละกลุ่ม แต่ละพาร์ติชันจะเริ่มอันดับใหม่ที่ 1

ในที่นี้ แต่ละแผนกจัดอันดับพนักงานของตนตามเงินเดือน โดยจัดการกรณีเงินเดือนเท่ากันด้วย DENSE_RANK ผู้มีเงินเดือนสูงสุดในแต่ละแผนกได้อันดับ 1 และพนักงานที่ได้รับเงินเดือนเท่ากันใช้อันดับร่วมกัน

SELECT
  department,
  name,
  salary,
  DENSE_RANK() OVER (
    PARTITION BY department
    ORDER BY salary DESC
  ) AS salary_rank
FROM employees;

ตัวอย่างแบบลงมือทำ: 3 อันดับแรกโดยรวมผู้ที่ได้คะแนนเท่ากัน

"คืนเงินเดือนสูงสุด 3 อันดับต่อแผนก และหากมีหลายคนได้อันดับที่สามเท่ากัน ให้รวมทุกคนไว้ด้วย" กรณีนี้ต้องใช้ RANK หรือ DENSE_RANK ไม่ใช่ ROW_NUMBER

การใช้ DENSE_RANK <= 3 จะเก็บระดับเงินเดือนที่ไม่ซ้ำกันสามอันดับแรกและพนักงานทุกคนในระดับเหล่านั้นไว้ ซึ่งตรงตามความหมายของ "รวมผู้ที่ได้อันดับเท่ากัน" อย่างพอดี

SELECT department, name, salary, salary_rank
FROM (
  SELECT department, name, salary,
         DENSE_RANK() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS salary_rank
  FROM employees
) t
WHERE salary_rank <= 3;

ตัวอย่างแบบลงมือทำ: เงินเดือนสูงสุดลำดับที่สอง

นี่คือคำถามสัมภาษณ์ SQL ที่โด่งดังที่สุด คำตอบที่รัดกุมใช้ DENSE_RANK เพื่อไม่ให้เงินเดือนสูงสุดที่ซ้ำกันผลักค่าลำดับที่สองที่แท้จริงออกไป

หากมีสามคนได้รับเงินเดือนสูงสุด DENSE_RANK = 2 จะระบุเงินเดือนถัดไปที่ไม่ซ้ำกันได้อย่างถูกต้อง ขณะที่ ROW_NUMBER = 2 จะส่งกลับผู้ได้รับเงินเดือนสูงสุดอีกคนหนึ่งเท่านั้น

SELECT DISTINCT salary AS second_highest
FROM (
  SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS dr
  FROM employees
) t
WHERE dr = 2;

RANK เทียบกับ DENSE_RANK สำหรับค่าสูงสุดลำดับที่ N

เหตุใดจึงใช้ DENSE_RANK แทน RANK สำหรับโจทย์ค่าที่สูงสุดลำดับที่ N เพราะ RANK เว้นช่องว่างของอันดับ เมื่อมีเงินเดือน 100, 100, 90 ค่า 90 จะมี RANK = 3 แต่มี DENSE_RANK = 2

หากคำถามขอ "เงินเดือนที่ไม่ซ้ำกันสูงสุดลำดับที่ 2" การกรองด้วย RANK = 2 จะไม่คืนผลลัพธ์ใด ขณะที่ DENSE_RANK = 2 จะคืนค่า 90 ได้อย่างถูกต้อง ให้จับคู่คำว่า "ไม่ซ้ำกันลำดับที่ N" กับ DENSE_RANK เสมอ

-- salaries 100,100,90
-- RANK:       1,1,3   -> WHERE rank = 2 returns NOTHING
-- DENSE_RANK: 1,1,2   -> WHERE dense_rank = 2 returns 90

หมายเหตุเกี่ยวกับความแตกต่างระหว่างภาษาถิ่น

ข่าวดีคือ ROW_NUMBER, RANK และ DENSE_RANK เป็นมาตรฐาน SQL และทำงานเหมือนกันทุกประการใน PostgreSQL, SQL Server, Oracle, MySQL 8 ขึ้นไป, BigQuery และ Snowflake ความหมายของกรณีคะแนนเท่ากันที่กล่าวมาข้างต้นใช้ได้กับทุกระบบ

ฟังก์ชันที่เกี่ยวข้องอย่าง PERCENT_RANK ต่อยอดจาก RANK เพื่อให้ตำแหน่งสัมพัทธ์ตั้งแต่ 0 ถึง 1 ซึ่งควรกล่าวถึงหากผู้สัมภาษณ์ถามเรื่องการจัดอันดับตามเปอร์เซ็นไทล์

ข้อผิดพลาดที่พบบ่อย

โปรดระวังเรื่องต่อไปนี้:

  • ใช้ ROW_NUMBER สำหรับ "ค่าสูงสุดลำดับที่ N" แล้วพลาดแถวที่มีค่าเท่ากัน
  • ใช้ RANK เมื่อคำถามหมายถึงค่าที่ไม่ซ้ำกัน แล้วได้ผลลัพธ์ว่างเนื่องจากมีช่องว่างของอันดับ
  • ลืมใส่ ORDER BY ภายใน OVER — การจัดอันดับไม่มีความหมายหากไม่มีส่วนนี้
  • กรองอันดับใน WHERE โดยตรง แทนที่จะกรองในคิวรีภายนอก

ตรวจสอบความเข้าใจอย่างรวดเร็ว

นำกฎเกี่ยวกับค่าที่เท่ากันไปใช้

สรุป: มีช่องว่างกับไม่มีช่องว่าง

ตอนนี้คุณสามารถเลือกฟังก์ชันจัดอันดับที่เหมาะสมได้ทันที:

  • ROW_NUMBER: ตัวเลขไม่ซ้ำกัน ไม่มีอันดับร่วม
  • RANK: ค่าที่เท่ากันใช้อันดับร่วมกัน แล้วมีช่องว่าง (1,2,2,4)
  • DENSE_RANK: ค่าที่เท่ากันใช้อันดับร่วมกัน โดยไม่มีช่องว่าง (1,2,2,3)
  • "ค่าสูงสุดที่ไม่ซ้ำกันลำดับที่ N" → DENSE_RANK; "N อันดับแรกโดยรวมผู้ที่ได้อันดับเท่ากัน" → RANK/DENSE_RANK; "หนึ่งแถวต่อแต่ละตำแหน่ง" → ROW_NUMBER

ถัดไป: วิธี กรอง ผลลัพธ์จากหน้าต่างจริง ๆ เนื่องจากไม่สามารถทำใน WHERE ได้

คำถามที่พบบ่อย

บทเรียน “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน”

คำถามคลาสสิกเรื่องการจัดอันดับที่มีช่องว่างกับไม่มีช่องว่างเมื่อค่าซ้ำกัน คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. OVER, PARTITION BY และ ORDER BY
  2. ROW_NUMBER สำหรับลำดับที่ไม่ซ้ำกัน
  3. RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน
  4. กรองจากผลลัพธ์ของฟังก์ชันวินโดว์
← กลับไปที่ Coding Interview Prep