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

จัดการค่าที่เสมอกันในแถว N อันดับแรก

เลือกใช้ RANK หรือ DENSE_RANK เมื่อค่าที่เสมอกันต้องถูกนำมารวมทั้งหมด

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

คำถามต่อเนื่องเรื่องกรณีคะแนนเท่ากัน

เมื่อคุณตอบโจทย์ N อันดับแรกด้วย ROW_NUMBER ได้แล้ว ผู้สัมภาษณ์อาจถามต่อให้ยากขึ้นว่า: "ถ้าพนักงานสองคนมีเงินเดือนเท่ากันพอดีตรงจุดตัด ควรรวมทั้งสองคนไว้หรือไม่"

คำถามนี้แยกผู้สมัครที่จำคำสั่งได้เพียงแบบเดียวออกจากผู้ที่เข้าใจความหมายของการจัดอันดับ คำตอบขึ้นอยู่กับการเลือกใช้ ROW_NUMBER, RANK หรือ DENSE_RANK บทนี้จะอธิบายว่าฟังก์ชันแต่ละแบบเหมาะกับจุดประสงค์ทางธุรกิจใด

ROW_NUMBER ซ่อนกรณีคะแนนเท่ากัน

ROW_NUMBER กำหนดจำนวนเต็มที่ไม่ซ้ำกันโดยเด็ดขาดให้แต่ละแถว แม้สองแถวจะมีค่าในคอลัมน์ที่ใช้เรียงลำดับเท่ากัน แถวหนึ่งจะได้ 2 และอีกแถวจะได้ 3 ตามลำดับที่ไม่แน่นอนแบบใดแบบหนึ่ง

ผลที่ตามมาคือ ตัวกรอง WHERE rn <= 3 จะส่งคืน3 แถวพอดี และอาจตัดแถวที่มีค่าเท่ากันซึ่งควรได้รวมอยู่ด้วยออกไปโดยไม่แจ้งให้ทราบ วิธีนี้เหมาะเมื่อคุณต้องการจำนวนแถวที่ตายตัวจริง ๆ แต่ไม่ถูกต้องเมื่อควรรวมทุกแถวที่มีค่าเท่ากัน

-- Salaries: 100, 90, 90, 80
-- ROW_NUMBER -> 1, 2, 3, 4  (the two 90s get 2 and 3 arbitrarily)
ROW_NUMBER() OVER (ORDER BY salary DESC)

RANK เว้นลำดับ

RANK กำหนดอันดับเดียวกันให้แถวที่มีค่าเท่ากัน จากนั้นข้ามค่าอันดับถัดไปเพื่อชดเชยแถวที่มีค่าเท่ากัน หากมีสองแถวเสมอกันที่อันดับ 2 ทั้งสองแถวจะได้อันดับ 2 และแถวถัดไปจะกระโดดไปเป็นอันดับ 4 ไม่ใช่ 3

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

-- Salaries: 100, 90, 90, 80
-- RANK -> 1, 2, 2, 4   (rank 3 is skipped)
RANK() OVER (ORDER BY salary DESC)

DENSE_RANK ไม่มีลำดับขาดหาย

DENSE_RANK กำหนดอันดับเดียวกันให้แถวที่มีค่าเท่ากันเช่นกัน แต่ไม่ข้ามอันดับถัดไป หากมีสองแถวเสมอกันที่อันดับ 2 ทั้งสองแถวจะได้อันดับ 2 และค่าที่แตกต่างถัดไปจะเป็นอันดับ 3

ใช้ DENSE_RANK เมื่อคำถามเกี่ยวกับค่าที่แตกต่างกัน เช่น "ระดับเงินเดือนสูงสุด 3 ระดับที่ไม่ซ้ำกัน" หรือ "ระดับราคาสูงสุด 3 ระดับ" ฟังก์ชันนี้นับค่าที่ไม่ซ้ำกัน ไม่ใช่จำนวนแถว

-- Salaries: 100, 90, 90, 80
-- DENSE_RANK -> 1, 2, 2, 3   (no gap)
DENSE_RANK() OVER (ORDER BY salary DESC)

เปรียบเทียบแบบเคียงข้างกัน

สำหรับรายการเงินเดือน 100, 90, 90, 80 ฟังก์ชันทั้งสามให้ผลดังนี้:

  • ROW_NUMBER: 1, 2, 3, 4
  • RANK: 1, 2, 2, 4
  • DENSE_RANK: 1, 2, 2, 3

ควรจดจำตารางนี้ให้ขึ้นใจ ผู้สัมภาษณ์อาจเพียงขอให้คุณเติมตารางสำหรับรายการที่กำหนด และหัวใจสำคัญคือการตอบเรื่องการเว้นลำดับให้ถูกต้อง

SELECT salary,
  ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn,
  RANK()       OVER (ORDER BY salary DESC) AS rnk,
  DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
FROM employees;

รวมทุกแถวที่คะแนนเท่ากันด้วย RANK

หากต้องการตอบคำถามว่า "3 อันดับแรก แต่รวมทุกคนที่มีอันดับเท่ากันตรงจุดตัด" ให้กรองด้วย RANK() <= 3 หากมีสองคนร่วมกันอยู่ที่อันดับ 3 ทั้งสองคนจะปรากฏในผลลัพธ์ ดังนั้นผลลัพธ์อาจมีมากกว่า 3 แถว

นี่คือจุดประสงค์ของคำถามที่ใช้ถ้อยคำว่า "3 อันดับในการแข่งขัน" แทนที่จะเป็น "แถวใดก็ได้ 3 แถว" โปรดระบุให้ชัดเจนว่าจำนวนแถวอาจมากกว่า N เมื่อมีกรณีคะแนนเท่ากัน

WITH ranked AS (
  SELECT name, department, salary,
         RANK() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rnk
  FROM employees
)
SELECT name, department, salary, rnk
FROM ranked
WHERE rnk <= 3
ORDER BY department, rnk;

ระดับที่แตกต่างกัน 3 อันดับแรกด้วย DENSE_RANK

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

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

WITH ranked AS (
  SELECT name, salary,
         DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
  FROM employees
)
SELECT name, salary, drnk
FROM ranked
WHERE drnk <= 3
ORDER BY drnk;

แนวทางตัดสินใจ

จับคู่ถ้อยคำกับฟังก์ชัน:

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

เมื่อข้อกำหนดไม่ชัดเจน ให้ถามว่า: "หากมีคะแนนเท่ากันตรงจุดตัด ควรรวมทุกแถวที่คะแนนเท่ากันไว้ หรือจำกัดจำนวนไว้ที่ N แถว" คำถามเพื่อขอความชัดเจนนี้เองก็ช่วยให้ได้คะแนน

ตัวตัดสินกรณีคะแนนเท่ากันยังคงสำคัญ

แม้จะใช้ RANK หรือ DENSE_RANK การเพิ่มคีย์ ORDER BY รองจะควบคุมลำดับการแสดงผลของแถวที่มีค่าเท่ากันและทำให้ผลลัพธ์คงที่ คีย์นี้ไม่เปลี่ยนว่าแถวใดผ่านเกณฑ์ แต่ช่วยให้ได้ผลลัพธ์ที่ทำซ้ำได้

สำหรับ ROW_NUMBER ตัวตัดสินกรณีคะแนนเท่ากันเป็นสิ่งจำเป็น เพราะเป็นตัวกำหนดว่าแถวใดที่มีค่าเท่ากันจะยังคงอยู่หลังการตัดด้วย rn

RANK() OVER (
  PARTITION BY department
  ORDER BY salary DESC, name ASC
) AS rnk

ตัวอย่างการทำงานจริง: ผู้ทำคะแนนสูงสุด

ตาราง game_scores มี player และ score ผู้สัมภาษณ์ต้องการ "ผู้เล่นทั้งหมดใน 2 อันดับคะแนนสูงสุด" หากมีผู้เล่นเสมอกันที่อันดับหนึ่ง ก็จะมีผู้เล่นสองคนอยู่ที่อันดับ 1 จากนั้นคะแนนที่แตกต่างถัดไปจะอยู่ที่อันดับ 2

คำว่า "อันดับ" ที่ไม่มีการข้ามลำดับหลังจากมีผู้เสมอกัน ชี้ไปที่ DENSE_RANK หากผู้สัมภาษณ์พูดว่า "2 อันดับแรกโดยมีการเว้นลำดับ" แทน คุณจะเปลี่ยนไปใช้ RANK โปรดฟังถ้อยคำที่ใช้ให้ละเอียด

WITH r AS (
  SELECT player, score,
         DENSE_RANK() OVER (ORDER BY score DESC) AS pos
  FROM game_scores
)
SELECT player, score, pos
FROM r
WHERE pos <= 2
ORDER BY pos, player;

ข้อผิดพลาดทั่วไปที่ควรหลีกเลี่ยง

จุดผิดพลาดที่ผู้สัมภาษณ์คอยสังเกต:

  • ใช้ ROW_NUMBER ทั้งที่คำถามต้องการรวมแถวที่มีค่าเท่ากัน ทำให้แถวที่ผ่านเกณฑ์ถูกตัดออกโดยไม่แจ้งให้ทราบ
  • สับสนเรื่องการเว้นลำดับระหว่าง RANK และ DENSE_RANK
  • ลืมว่าตัวกรองของ RANK/DENSE_RANK อาจส่งคืนมากกว่า N แถว แล้วอ้างว่าผลลัพธ์ไม่ถูกต้อง
  • ละเว้น PARTITION BY เมื่อการเลือก N อันดับแรกต้องทำแยกตามกลุ่ม ทำให้จัดอันดับทั้งตารางแทน

ตรวจสอบอย่างรวดเร็ว

เลือกฟังก์ชันจัดอันดับที่เหมาะสมกับพฤติกรรมเมื่อค่ากันที่ระบุ

สรุป: การจัดการกรณีค่าเท่ากัน

ฟังก์ชันสามแบบ พฤติกรรมเมื่อค่าเท่ากันสามรูปแบบ:

  • ROW_NUMBER: ไม่ซ้ำกันเสมอ ได้จำนวน N แถวพอดี และจัดการแถวที่ค่าเท่ากันตามอำเภอใจ
  • RANK: แถวที่ค่าเท่ากันจะมีอันดับเดียวกัน จากนั้นจะเกิดช่องว่างของอันดับ
  • อันดับแบบหนาแน่น: แถวที่ค่าเท่ากันจะมีอันดับเดียวกัน ไม่มีช่องว่าง และนับเฉพาะค่าที่แตกต่างกัน

เลือกใช้ตามถ้อยคำของคำถาม หากกำกวมให้ถามเพื่อขอคำชี้แจง และจำไว้ว่าเงื่อนไขตัวกรอง RANK/DENSE_RANK อาจคืนค่ามากกว่า N แถวได้โดยตั้งใจ

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

บทเรียน “จัดการค่าที่เสมอกันในแถว N อันดับแรก” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “จัดการค่าที่เสมอกันในแถว N อันดับแรก”

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

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

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

บทเรียน “จัดการค่าที่เสมอกันในแถว N อันดับแรก” ใช้เวลานานแค่ไหน

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

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

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

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

  1. แถว N อันดับแรกต่อกลุ่มด้วย ROW_NUMBER
  2. จัดการค่าที่เสมอกันในแถว N อันดับแรก
  3. ลบแถวซ้ำอย่างปลอดภัย
  4. เก็บแถวล่าสุดของแต่ละคีย์
← กลับไปที่ SQL Interview Prep