先問你一個問題:你在網購網站看到一堆商品都塞在同一頁時會怎麼辦?沒錯,就是點下一頁。那你知道背後發生什麼事嗎?其實就是 SQL 的魔法啦 —— 用 OFFSET 這個指令來跳過資料列。今天要跟你聊聊什麼是 OFFSET、它有什麼用、怎麼用,還有為什麼它是分頁功能的基礎。
OFFSET 是 SQL 裡的一個關鍵字,可以讓你在查詢結果裡跳過指定數量的資料列。就像翻書一樣:你可以「跳過」前 10 行,直接從第 11 行開始看。
語法
SELECT 欄位1, 欄位2
FROM 表格
OFFSET 跳過_幾行;
OFFSET—— 跳過資料列的關鍵字。- 跳過_幾行 —— 你想要跳過的資料列數量。
OFFSET 的簡單範例
假設我們有一個 students 表格,裡面有這些資料:
| id | name | age |
|---|---|---|
| 1 | 愛麗絲 | 22 |
| 2 | 鮑勃 | 24 |
| 3 | 克拉拉 | 23 |
| 4 | 丹 | 21 |
| 5 | 伊娃 | 25 |
我們想要從第三個學生開始顯示。可以這樣查:
SELECT *
FROM students
OFFSET 2;
結果:
| id | name | age |
|---|---|---|
| 3 | 克拉拉 | 23 |
| 4 | 丹 | 21 |
| 5 | 伊娃 | 25 |
SQL「跳過」了前兩行(愛麗絲和鮑勃),從第三行開始給你結果。就像用書籤一樣:「這頁看過了,翻下一頁」。
OFFSET 跟 LIMIT 一起用
OFFSET 通常會跟 LIMIT 一起用。這樣你可以同時跳過幾行,又只拿你要的那幾筆資料。這對做分頁(page = 頁面)超級有用 —— 一次顯示幾行資料。
假設我們想每次顯示 2 筆,從第三行開始。查詢會長這樣:
SELECT *
FROM students
LIMIT 2
OFFSET 2;
結果:
| id | name | age |
|---|---|---|
| 3 | 克拉拉 | 23 |
| 4 | 丹 | 21 |
邏輯是這樣:
OFFSET 2先跳過前兩行:愛麗絲和鮑勃。LIMIT 2再從剩下的拿兩行。
分頁怎麼做
現在來到最有趣的部分 —— 分頁啦。想像你要做一個有學生列表的網頁,每頁只想顯示 2 筆資料。怎麼辦?
基本原則:
- 第一頁不跳過任何行:
OFFSET 0。 - 第二頁跳過 2 行:
OFFSET 2。 - 第三頁跳過 4 行:
OFFSET 4。 - 以此類推...
範例:顯示第二頁
第一頁會顯示第 1 和 2 筆(愛麗絲和鮑勃)。第二頁就是第 3 和 4 筆(克拉拉和丹)。
SELECT *
FROM students
ORDER BY id
LIMIT 2
OFFSET 2;
結果:
| id | name | age |
|---|---|---|
| 3 | 克拉拉 | 23 |
| 4 | 丹 | 21 |
範例:顯示第三頁
第三頁會是第 5 和 6 筆(如果有的話)。
SELECT *
FROM students
ORDER BY id
LIMIT 2
OFFSET 4;
結果:
| id | name | age |
|---|---|---|
| 5 | 伊娃 | 25 |
OFFSET 計算公式
做分頁系統時,可以用這個公式自動算 OFFSET:
OFFSET = (頁碼 - 1) * 每頁_幾筆
舉例:
- 第一頁:
(1 - 1) * 2 = 0。 - 第二頁:
(2 - 1) * 2 = 2。 - 第三頁:
(3 - 1) * 2 = 4。
效能注意事項
當你在大表格裡用 OFFSET,尤其是很後面的頁面時,效能可能會變差。因為 PostgreSQL 還是會把被跳過的資料列都掃過一遍。比如 OFFSET 10000,資料庫還是會先看過前一萬行才給你結果。這時可以考慮其他做法,比如用唯一 id 當分頁的標記。
替代方案:用游標分頁
想優化的話,可以用「游標」的方式。不是用 OFFSET 跳過資料列,而是記住上一頁最後一筆的 id,下次查詢時用這個 id 當條件:
SELECT *
FROM students
WHERE id > 最後_顯示的_id
ORDER BY id
LIMIT 2;
這種做法在大表格時會快很多。
分頁的實際應用
分頁 在大多數網頁應用都會用到:網購、部落格、後台管理面板。舉例:
- 網購網站商品列表;
- CRM 系統的用戶列表;
- 新聞動態分頁顯示。
分析大量資料時,分頁也很有用,可以分批處理。
用 OFFSET 常見錯誤
剛學 OFFSET 時常常會踩雷,這裡列幾個常見錯誤:
沒加排序。 如果你沒加 ORDER BY,OFFSET 的結果順序可能亂七八糟。
錯誤查詢:
SELECT * FROM students
OFFSET 5;
正確查詢:
SELECT * FROM students
ORDER BY id
OFFSET 5;
OFFSET 值設錯。 如果設太大,結果會是空的。
效能問題。 剛剛說過,OFFSET 很大時效能會很差。
沒加過濾。 如果你用 OFFSET 跟 LIMIT 但沒加 WHERE 過濾,可能會撈到一堆你不想要的資料,效能也會變差。
指令順序。 SQL 指令順序很嚴格:要先 LIMIT,再 OFFSET。可以省略,但不能顛倒順序。
GO TO FULL VERSION