RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน
คำถามคลาสสิกเรื่องการจัดอันดับที่มีช่องว่างกับไม่มีช่องว่างเมื่อค่าซ้ำกัน
RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL 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) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน”
คำถามคลาสสิกเรื่องการจัดอันดับที่มีช่องว่างกับไม่มีช่องว่างเมื่อค่าซ้ำกัน คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม
ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- OVER, PARTITION BY และ ORDER BY
- ROW_NUMBER สำหรับลำดับที่ไม่ซ้ำกัน
- RANK เทียบกับ DENSE_RANK เมื่อค่าซ้ำกัน
- กรองจากผลลัพธ์ของฟังก์ชันวินโดว์