Pagination แบบเดิมมัก Query 2 ครั้ง: 1) นับ Total Rows 2) ดึงข้อมูลหน้าปัจจุบัน แต่สามารถทำได้ใน Query เดียวด้วย SQL_CALC_FOUND_ROWS และ FOUND_ROWS()
วิธีเดิม (2 Queries)
-- Query 1: นับทั้งหมด
SELECT COUNT(*) FROM RowCountDemo WHERE id > 0;
-- Query 2: ดึงข้อมูลหน้าที่ 1 (10 รายการ)
SELECT * FROM RowCountDemo WHERE id > 0 LIMIT 0, 10;
วิธี Single Query (MySQL Specific)
-- Query เดียว: ใช้ SQL_CALC_FOUND_ROWS
SELECT SQL_CALC_FOUND_ROWS * FROM RowCountDemo WHERE id > 0 LIMIT 0, 10;
-- ตามด้วย: ดึง Total Rows
SELECT FOUND_ROWS();
ผลลัพธ์
-- Query แรก: ข้อมูล 10 แถว
+------+-------+
| ID | Name |
+------+-------+
| 1 | Larry |
| 2 | John |
| ... | ... |
| 10 | Gavin |
+------+-------+
-- Query ที่สอง: FOUND_ROWS()
+--------------+
| FOUND_ROWS() |
+--------------+
| 100 | <-- Total rows ทั้งหมด (ไม่ใช่แค่ 10)
+--------------+
⚠️ หมายเหตุสำคัญ: SQL_CALC_FOUND_ROWS ถูก Deprecated
ตั้งแต่ MySQL 8.0.17 แล้ว SQL_CALC_FOUND_ROWS และ FOUND_ROWS() ถูก Deprecated และอาจถูกลบในอนาคต
แนวทางทดแทน (Modern Approach)
1. ใช้ 2 Queries แยกกัน (แนะนำ - ชัดเจนและรองรับ Index)
-- Count (ใช้ Index ได้เร็ว)
SELECT COUNT(*) FROM RowCountDemo WHERE id > 0;
-- Data
SELECT * FROM RowCountDemo WHERE id > 0 LIMIT 0, 10;
2. Keyset Pagination / Seek Method (ประสิทธิภาพดีที่สุด)
-- หน้าแรก
SELECT * FROM RowCountDemo WHERE id > 0 ORDER BY id LIMIT 10;
-- หน้าถัดไป (ใช้ ID สุดท้ายของหน้าก่อน)
SELECT * FROM RowCountDemo WHERE id > 10 ORDER BY id LIMIT 10;
3. Window Function (MySQL 8.0+)
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn,
COUNT(*) OVER () AS total
FROM RowCountDemo WHERE id > 0
) t
WHERE rn BETWEEN 1 AND 10;
สรุปแนะนำ
- ❌ หลีกเลี่ยง
SQL_CALC_FOUND_ROWS(Deprecated) - ✅ ใช้ 2 Queries แยกกัน (Simple, Fast with Index)
- ✅ ใช้ Keyset Pagination สำหรับ Deep Paging / Large Dataset
- ✅ ใช้ Window Function ถ้าต้องการ Single Query (MySQL 8.0+)