ใช้ OFFSET และ LIMIT สำหรับ Skip Pattern
เมื่อต้องการ Select แถวที่ n, n+3, n+6... (ข้าม 2 แถว แสดง 1 แถว) ใช้ OFFSET และ LIMIT ใน Subquery
ตัวอย่าง: เรียง DESC แล้วข้าม 2 แถว แสดง 5 แถว
CREATE TABLE DemoTable617 (
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(100)
);
INSERT INTO DemoTable617(FirstName) VALUES
('John'), ('Sam'), ('Carol'), ('Mike'), ('David'),
('Bob'), ('Robert'), ('Chris'), ('Mike'), ('Adam');
Query: เรียง FirstName DESC, ข้าม 2 แถวแรก, แสดง 5 แถว, แล้วเรียงกลับตาม Id ASC
SELECT tbl.*
FROM (
SELECT * FROM DemoTable617
ORDER BY FirstName DESC
LIMIT 5 OFFSET 2
) AS tbl
ORDER BY tbl.Id;
ผลลัพธ์:
+----+-----------+
| Id | FirstName |
+----+-----------+
| 1 | John |
| 4 | Mike |
| 5 | David |
| 8 | Chris |
| 9 | Mike |
+----+-----------+
อธิบายขั้นตอน
ORDER BY FirstName DESC→ Sam, Robert, Mike, Mike, John, David, Chris, Carol, Bob, AdamOFFSET 2→ ข้าม Sam, RobertLIMIT 5→ เอา Mike, Mike, John, David, Chris- Outer
ORDER BY Id→ เรียงตาม Id: 1(John), 4(Mike), 5(David), 8(Chris), 9(Mike)
รูปแบบทั่วไป: Select Every Nth Row
-- Select ทุก 3 แถว (Row 1, 4, 7, 10...)
SELECT * FROM (
SELECT *, @rownum := @rownum + 1 AS rn
FROM DemoTable617, (SELECT @rownum := 0) r
ORDER BY Id
) t
WHERE rn % 3 = 1;
MySQL 8.0+: ใช้ ROW_NUMBER()
WITH numbered AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Id) AS rn
FROM DemoTable617
)
SELECT * FROM numbered WHERE rn % 3 = 1;
ตัวอย่าง Sampling: Random 10% ของข้อมูล
-- Bernoulli Sampling (ประมาณ 10%)
SELECT * FROM DemoTable617 WHERE RAND() < 0.1;
-- Systematic Sampling (ทุก 10 แถว)
WITH numbered AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Id) AS rn
FROM DemoTable617
)
SELECT * FROM numbered WHERE rn % 10 = 1;
Performance Note
OFFSETมาก = ช้า (ต้อง Scan Offset rows)- Subquery + LIMIT/OFFSET ยัง Scan ตาม Offset ใน Inner Query
- Keyset Pagination (WHERE id > last_id) เร็วกว่าสำหรับ Deep Skip