Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

วิธีเลือก 3 คะแนนสูงสุด และจัดเรียงตามชื่ออักษรใน MySQL

การเลือก Top-N พร้อมจัดเรียงรองด้วย Subquery และ ORDER BY

เมื่อต้องการเลือกข้อมูล Top-N ตามคอลัมน์หนึ่ง แล้วจัดเรียงผลลัพธ์ตามอีกคอลัมน์หนึ่ง ให้ใช้ Subquery (Derived Table) เพื่อกรอง Top-N ก่อน แล้วค่อยจัดเรียงอีกครั้ง

รูปแบบคำสั่ง

SELECT * FROM (
    SELECT columns FROM table_name 
    ORDER BY primary_sort_column DESC, secondary_sort_column ASC 
    LIMIT N
) AS subquery_alias
ORDER BY secondary_sort_column;

ตัวอย่าง: เลือก 3 คนคะแนนสูงสุด แล้วจัดเรียงตามชื่อ A-Z

1. สร้างตารางและเพิ่มข้อมูล

CREATE TABLE DemoTable (
    Name VARCHAR(40),
    Score INT
);

INSERT INTO DemoTable VALUES ('Chris', 45);
INSERT INTO DemoTable VALUES ('Bob', 98);
INSERT INTO DemoTable VALUES ('David', 78);
INSERT INTO DemoTable VALUES ('Mike', 96);
INSERT INTO DemoTable VALUES ('Carol', 43);

2. ดูข้อมูลทั้งหมด

SELECT * FROM DemoTable;

ผลลัพธ์:

+-------+-------+
| Name  | Score |
+-------+-------+
| Chris | 45    |
| Bob   | 98    |
| David | 78    |
| Mike  | 96    |
| Carol | 43    |
+-------+-------+

3. Query หลัก: Top 3 Score แล้วเรียงชื่อ A-Z

SELECT * FROM (
    SELECT Name, Score 
    FROM DemoTable 
    ORDER BY Score DESC, Name ASC 
    LIMIT 3
) AS tbl 
ORDER BY Name;

ผลลัพธ์:

+-------+-------+
| Name  | Score |
+-------+-------+
| Bob   | 98    |
| David | 78    |
| Mike  | 96    |
+-------+-------+

การทำงานทีละขั้นตอน

  1. Subquery (ภายใน): เรียงตาม Score DESC (มากไปน้อย), Name ASC (อักษร) → ได้ Bob(98), Mike(96), David(78) แล้ว LIMIT 3
  2. Outer Query (ภายนอก): นำ 3 แถวที่ได้มา เรียงใหม่ตาม Name ASC → Bob, David, Mike

เหตุผลที่ต้องใช้ Subquery

หากเขียน ORDER BY Score DESC, Name ASC LIMIT 3 แล้วตามด้วย ORDER BY Name ในระดับเดียว MySQL จะใช้ ORDER BY ตัวสุดท้าย ทำให้ Top 3 ไม่ถูกต้อง

MySQL 8.0+ : ใช้ CTE (Common Table Expression) อ่านง่ายกว่า

WITH TopScores AS (
    SELECT Name, Score 
    FROM DemoTable 
    ORDER BY Score DESC, Name ASC 
    LIMIT 3
)
SELECT * FROM TopScores ORDER BY Name;

กรณีคะแนนเท่ากัน (Tie-breaking)

ใน Subquery ใช้ ORDER BY Score DESC, Name ASC เพื่อให้คะแนนเท่ากัน เรียงตามชื่ออักษร ก่อน LIMIT

การใช้งานกับ Window Functions (MySQL 8.0+)

SELECT Name, Score FROM (
    SELECT Name, Score,
           ROW_NUMBER() OVER (ORDER BY Score DESC, Name ASC) AS rn
    FROM DemoTable
) t WHERE rn <= 3
ORDER BY Name;