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

เงินเดือนสูงสุดอันดับสอง ห้าวิธี

เปรียบเทียบวิธีใช้คิวรีย่อย LIMIT/OFFSET และฟังก์ชันวินโดว์

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

คำถามที่ทุกคนต้องเจอ

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

สมมติว่ามีตาราง employee ซึ่งมีคอลัมน์ id และ salary หน้าที่ของคุณคือคืนค่าเงินเดือนที่สูงเป็นอันดับสองแบบไม่ซ้ำกัน

  • หากเงินเดือนคือ 300, 200, 200, 100 คำตอบคือ 200 ไม่ใช่แถวที่สอง
  • หากไม่มีเงินเดือนลำดับที่สองที่แตกต่างกัน คำตอบที่คาดหวังโดยทั่วไปคือ NULL

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

CREATE TABLE employee (
  id     INT PRIMARY KEY,
  salary INT
);

วิธีที่ 1: MAX ของค่าที่ต่ำกว่า MAX

วิธีแก้ที่เข้าใจง่ายที่สุดคือ เงินเดือนที่สูงเป็นอันดับสองคือเงินเดือนที่มีค่าสูงที่สุดในบรรดาเงินเดือนที่ต่ำกว่าค่าสูงสุดโดยเคร่งครัด

รูปแบบนี้อ่านแทบเหมือนประโยคภาษาอังกฤษ และใช้ได้กับรูปแบบภาษาของระบบเอสคิวแอลทุกระบบ แบบสอบถามย่อยภายในจะค้นหาค่าสูงสุด ส่วน MAX ภายนอกจะค้นหาค่าที่ใหญ่ที่สุดซึ่งต่ำกว่าค่านั้น

ข้อดีเพิ่มเติม: หากไม่มีเงินเดือนลำดับที่สองที่แตกต่างกัน MAX ภายนอกจะรวมแถวเป็นศูนย์แถวและคืนค่า NULL โดยอัตโนมัติ การได้ค่า NULL โดยไม่ต้องเขียนเพิ่มนี้ตรงกับสิ่งที่ผู้สัมภาษณ์ต้องการพอดี

SELECT MAX(salary) AS second_highest
FROM employee
WHERE salary < (SELECT MAX(salary) FROM employee);

เหตุใดคิวรีย่อยจึงจัดการค่าซ้ำได้

สังเกตว่าเราไม่เคยใช้ DISTINCT ในวิธีที่ 1 แต่ยังจัดการค่าซ้ำได้อย่างถูกต้อง

หากมีคนสามคนได้เงินเดือน 200 และผู้ที่ได้เงินเดือนสูงสุดได้รับ 300 คิวรีภายในจะส่งคืน 300 ตัวกรองภายนอกจะเก็บทุกแถวที่มีค่าน้อยกว่า 300 และ MAX ของแถวเหล่านั้นคือ 200 ไม่ว่าจะมีค่า 200 อยู่กี่ค่าก็ตาม

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

วิธีที่ 2: LIMIT ร่วมกับ OFFSET

ใน MySQL และ PostgreSQL คุณสามารถเรียงเงินเดือนที่ไม่ซ้ำกันจากมากไปน้อย แล้วข้ามค่าแรกไปได้

  • OFFSET 1 ข้ามค่าสูงสุด
  • LIMIT 1 เก็บไว้เพียงค่าถัดไป

DISTINCT จำเป็นอย่างยิ่งในกรณีนี้ มิฉะนั้นเงินเดือนสูงสุดที่ซ้ำกันจะทำให้ OFFSET 1 ไปอยู่ที่ค่าซ้ำของค่าสูงสุด แทนที่จะเป็นค่าที่สูงเป็นอันดับสองจริง ๆ

ข้อควรระวัง: หากไม่มีค่าที่ไม่ซ้ำกันเป็นอันดับสอง วิธีนี้จะส่งคืนศูนย์แถว ไม่ใช่ NULL เราจะแก้กรณีขอบนี้ในบทเรียนที่ 4

SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

วิธีที่ 3: FETCH สำหรับ SQL Server และ Oracle

SQL Server และ Oracle รุ่นใหม่ไม่รองรับ LIMIT ... OFFSET แต่ใช้ไวยากรณ์มาตรฐาน ANSI อย่าง OFFSET ... FETCH แทน

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

SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;

วิธีที่ 4: ฟังก์ชันหน้าต่าง DENSE_RANK

แนวทางสมัยใหม่ที่รองรับการขยายขนาดใช้ฟังก์ชันหน้าต่าง DENSE_RANK กำหนดอันดับ 1 ให้กับเงินเดือนสูงสุด อันดับ 2 ให้กับเงินเดือนถัดไปที่ไม่ซ้ำกัน และกำหนดอันดับเดียวกันให้กับเงินเดือนที่เท่ากันโดยไม่เว้นลำดับ

เราคำนวณอันดับในคิวรีย่อย จากนั้นจึงกรองหาอันดับ 2 ในคิวรีภายนอก โปรดจำไว้ว่าคุณไม่สามารถกรองฟังก์ชันหน้าต่างโดยตรงใน WHERE ได้ ดังนั้นจึงจำเป็นต้องมีคิวรีย่อยที่ครอบไว้

SELECT salary AS second_highest
FROM (
  SELECT salary,
         DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
  FROM employee
) ranked
WHERE rnk = 2;

เหตุใดจึงใช้ DENSE_RANK ไม่ใช่ RANK หรือ ROW_NUMBER

การเลือกฟังก์ชันจัดอันดับมีผลต่อความหมายแบบค่าไม่ซ้ำกัน:

  • ROW_NUMBER กำหนดหมายเลขไม่ซ้ำกันให้ทุกแถว ดังนั้นคนสองคนที่ได้เงินเดือน 300 จะเป็นแถวที่ 1 และ 2 และอันดับ 2 จะเป็นเงินเดือนสูงสุดซ้ำอีกครั้ง ไม่ถูกต้อง
  • RANK เว้นลำดับหลังค่าที่เท่ากัน: คนสองคนที่ได้เงินเดือน 300 จะได้อันดับ 1 จากนั้นเงินเดือนถัดไปจะกระโดดไปเป็นอันดับ 3 ทำให้คุณพลาดค่านั้นเมื่อค้นหาอันดับ 2 ไม่ถูกต้อง
  • DENSE_RANK กำหนดอันดับเดียวกันให้ค่าที่เท่ากันและไม่เว้นลำดับ ดังนั้นอันดับ 2 จึงเป็นเงินเดือนลำดับที่สองที่ไม่ซ้ำกันเสมอ ถูกต้อง

วิธีที่ 5: การนับด้วยคิวรีย่อยแบบสัมพันธ์

เทคนิคคลาสสิกก่อนมีฟังก์ชันหน้าต่าง: เงินเดือนจะเป็นเงินเดือนสูงสุดลำดับที่ N หากมีเงินเดือนที่ไม่ซ้ำกันและสูงกว่าค่านั้นอย่างเคร่งครัดอยู่ בדיוק N - 1 ค่า

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

วิธีนี้ต่อยอดไปยังเงินเดือนสูงสุดลำดับที่ N ได้อย่างเป็นธรรมชาติ เพียงเปลี่ยนการนับเป็น N - 1 จึงเป็นเหตุผลที่ผู้สัมภาษณ์ชอบให้ผู้สมัครแสดงวิธีนี้

SELECT salary AS second_highest
FROM employee e
WHERE 1 = (
  SELECT COUNT(DISTINCT e2.salary)
  FROM employee e2
  WHERE e2.salary > e.salary
);

ตัวอย่างตั้งแต่ต้นจนจบ

กำหนดเงินเดือนเป็น 500, 500, 350, 350, 100

  • วิธีที่ 1: MAX คือ 500 และค่าที่มากที่สุดซึ่งน้อยกว่า 500 คือ 350 คำตอบคือ 350
  • วิธีที่ 4 (DENSE_RANK): 500 -> อันดับ 1, 350 -> อันดับ 2, 100 -> อันดับ 3 อันดับ 2 คือ 350
  • วิธีที่ 5: สำหรับเงินเดือน 350 มีเงินเดือนที่ไม่ซ้ำกันสูงกว่าอยู่พอดีหนึ่งค่า (500) ตรงตามเงื่อนไข คำตอบคือ 350

ทั้งห้าวิธีให้ผลตรงกัน: เงินเดือนสูงสุดลำดับที่สองที่ไม่ซ้ำกันคือ 350 แม้ว่าจะมีค่าซ้ำกันอยู่ก็ตาม

ควรเลือกวิธีใด

คำแนะนำสำหรับการสัมภาษณ์:

  • ระบุคำถามก่อน: "คุณต้องการเงินเดือนที่ไม่ซ้ำกัน และให้ส่งคืน NULL หากไม่มีค่าหรือไม่" การขอความชัดเจนช่วยเพิ่มคะแนน
  • DENSE_RANK เป็นคำตอบเริ่มต้นที่ดีที่สุด และต่อยอดไปยังลำดับที่ N รวมถึงการจัดอันดับรายกลุ่มได้อย่างราบรื่น
  • MAX ที่น้อยกว่า MAX เป็นคำตอบแบบบรรทัดเดียวที่ดีที่สุด และส่งคืน NULL ได้โดยไม่ต้องทำอะไรเพิ่ม
  • LIMIT/OFFSET กระชับ แต่ขึ้นกับระบบฐานข้อมูล และจะไม่ส่งคืนแถวในกรณีขอบ

การอธิบายข้อแลกเปลี่ยนให้ผู้สัมภาษณ์ได้ยินคือสิ่งที่ทำให้คำตอบระดับกลางแตกต่างจากคำตอบระดับเริ่มต้น

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

ระวังกับดักเหล่านี้ที่ผู้สัมภาษณ์มักวางไว้:

  • ใช้ ROW_NUMBER แทน DENSE_RANK จนได้เงินเดือนสูงสุดซ้ำสองครั้ง
  • ลืมใส่ DISTINCT ในวิธี LIMIT/OFFSET เมื่อมีค่าสูงสุดซ้ำกัน
  • เข้าใจผิดว่า ORDER BY salary DESC LIMIT 1,1 จะส่งคืนค่าที่ไม่ซ้ำกัน ทั้งที่ไม่เป็นเช่นนั้น
  • ส่งคืนแถวที่สองแทนที่จะเป็นค่าที่สอง

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจของคุณเกี่ยวกับการเลือกฟังก์ชันจัดอันดับ

สรุป

ตอนนี้คุณมีห้าวิธีในการค้นหาเงินเดือนสูงสุดลำดับที่สอง:

  • MAX ที่ต่ำกว่า MAX - ใช้ได้กับหลายระบบ และส่งคืน NULL ได้โดยไม่ต้องทำอะไรเพิ่ม
  • LIMIT/OFFSET และ OFFSET/FETCH - กระชับ แต่ขึ้นกับระบบฐานข้อมูล
  • DENSE_RANK - คำตอบเริ่มต้นที่รองรับการขยายขนาดและจัดการค่าที่เท่ากันได้อย่างถูกต้อง
  • การนับแบบสัมพันธ์ - เรียบง่ายและต่อยอดไปยังลำดับที่ N ได้

ประเด็นสำคัญคือ ให้ถามว่าคุณต้องการค่าที่ไม่ซ้ำกันหรือไม่ เลือกใช้ DENSE_RANK เมื่อมีค่าที่เท่ากัน และจำไว้ว่าวิธีใดส่งคืน NULL และวิธีใดไม่ส่งคืนแถวเมื่อไม่มีค่าที่สอง

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

บทเรียน “เงินเดือนสูงสุดอันดับสอง ห้าวิธี” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “เงินเดือนสูงสุดอันดับสอง ห้าวิธี”

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

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

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

บทเรียน “เงินเดือนสูงสุดอันดับสอง ห้าวิธี” ใช้เวลานานแค่ไหน

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

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

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

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

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