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

MySQL หาค่าที่เกิดบ่อยที่สุด (Top N) จากตารางมี Duplicate

หา Top N ค่าที่เกิดบ่อยที่สุดด้วย GROUP BY และ COUNT

ตัวอย่าง: วิชาที่นักเรียนเลือกมากที่สุด

CREATE TABLE DemoTable610 (SubjectName VARCHAR(100));

INSERT INTO DemoTable610 VALUES
('MySQL'), ('Java'), ('MySQL'), ('MongoDB'), ('MySQL'),
('MySQL'), ('Java'), ('MongoDB'), ('C'), ('C++'),
('MongoDB'), ('MySQL'), ('Java'), ('Python'), ('MySQL');

Query: หา Top 2 วิชาที่มีนักเรียนมากที่สุด

SELECT SubjectName 
FROM (
    SELECT SubjectName 
    FROM DemoTable610 
    GROUP BY SubjectName 
    ORDER BY COUNT(SubjectName) DESC 
    LIMIT 2
) AS tbl
ORDER BY SubjectName;

ผลลัพธ์: Java, MySQL (เรียง A-Z)

+-------------+
| SubjectName |
+-------------+
| Java        |
| MySQL       |
+-------------+

อธิบาย Logic

  1. GROUP BY SubjectName - จับกลุ่มตามชื่อวิชา
  2. COUNT(SubjectName) - นับจำนวนในแต่ละกลุ่ม
  3. ORDER BY COUNT(...) DESC - เรียงจากมากไปน้อย
  4. LIMIT 2 - เอา 2 อันดับแรก
  5. Outer Query ORDER BY SubjectName - เรียงผลลัพธ์สุดท้ายตามตัวอักษร

รูปแบบที่ทันสมัยกว่า: Window Function (MySQL 8.0+)

WITH ranked AS (
    SELECT 
        SubjectName,
        COUNT(*) AS cnt,
        ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) AS rn
    FROM DemoTable610
    GROUP BY SubjectName
)
SELECT SubjectName, cnt
FROM ranked
WHERE rn <= 2
ORDER BY SubjectName;

ตัวอย่าง: Top 3 พร้อมแสดง Count

SELECT SubjectName, COUNT(*) AS frequency
FROM DemoTable610
GROUP BY SubjectName
ORDER BY frequency DESC, SubjectName
LIMIT 3;

ข้อควรระวัง: Tie (คะแนนเท่ากัน)

LIMIT 2 จะตัดทิ้งค่าที่เท่ากันอันดับ 3 แม้จะมี Count เท่ากัน

ใช้ DENSE_RANK() แทน ROW_NUMBER() ถ้าต้องการรวม Tie:

WITH ranked AS (
    SELECT SubjectName, COUNT(*) AS cnt,
           DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS dr
    FROM DemoTable610
    GROUP BY SubjectName
)
SELECT SubjectName, cnt FROM ranked WHERE dr <= 2;

Performance Tips

  • Index บน SubjectName ช่วย GROUP BY เร็วขึ้น
  • ตารางใหญ่: ใช้ Summary Table / Materialized View แทน Query จริงทุกครั้ง
  • COUNT(*) เร็วกว่า COUNT(column) (นับทุกแถว ไม่เช็ค NULL)