การดึงแถวทั้งหมดที่มีค่าสูงสุด (MAX) รวมถึงค่าซ้ำด้วย JOIN
เมื่อต้องการดึง ทุกแถว ที่มีค่าเท่ากับค่าสูงสุด (MAX) ไม่ใช่แค่ค่า MAX เดียว ใช้เทคนิค JOIN กับ subquery ที่หา MAX
สร้างตารางและข้อมูล (มีค่าซ้ำ)
mysql> create table DemoTable1389 (
-> StudentId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentMarks int
-> );
Query OK, 0 rows affected (2.73 sec)
mysql> insert into DemoTable1389(StudentMarks) values(40);
mysql> insert into DemoTable1389(StudentMarks) values(40);
mysql> insert into DemoTable1389(StudentMarks) values(68);
mysql> insert into DemoTable1389(StudentMarks) values(78);
mysql> insert into DemoTable1389(StudentMarks) values(97);
mysql> insert into DemoTable1389(StudentMarks) values(97);
mysql> insert into DemoTable1389(StudentMarks) values(97);
ข้อมูลทั้งหมด
+-----------+--------------+ | StudentId | StudentMarks | +-----------+--------------+ | 1 | 40 | | 2 | 40 | | 3 | 68 | | 4 | 78 | | 5 | 97 | | 6 | 97 | | 7 | 97 | +-----------+--------------+
คำสั่ง JOIN กับ Subquery MAX
mysql> select tbl.StudentId, tbl.StudentMarks
-> from DemoTable1389 tbl
-> join (
-> select max(StudentMarks) as MaxMarks from DemoTable1389
-> ) tbl1
-> on tbl1.MaxMarks = tbl.StudentMarks;
ผลลัพธ์ (ได้ 3 แถวที่มีค่า 97)
+-----------+--------------+ | StudentId | StudentMarks | +-----------+--------------+ | 5 | 97 | | 6 | 97 | | 7 | 97 | +-----------+--------------+
วิธีอื่นใน MySQL 8.0+: Window Function
SELECT StudentId, StudentMarks
FROM (
SELECT StudentId, StudentMarks,
RANK() OVER (ORDER BY StudentMarks DESC) as rnk
FROM DemoTable1389
) t
WHERE rnk = 1;
RANK() ให้อันดับเดียวกันสำหรับค่าเท่ากัน (เหมาะกับ duplicate max) ส่วน ROW_NUMBER() จะให้ลำดับต่างกันไป
เปรียบเทียบวิธีต่างๆ
| วิธี | รองรับ MySQL | ประสิทธิภาพ | ความซับซ้อน |
|---|---|---|---|
| JOIN + Subquery MAX | ทุกเวอร์ชัน | สแกนตาราง 2 ครั้ง | ต่ำ |
| WHERE col = (SELECT MAX(...)) | ทุกเวอร์ชัน | สแกนตาราง 2 ครั้ง | ต่ำมาก |
| Window Function (RANK) | 8.0+ | สแกนครั้งเดียว + sort | ปานกลาง |