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

MySQL Pagination แบบไม่ต้อง Query 2 ครั้ง (Single Query)

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+)