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