MySQL 中的LIMIT
子句可以用於限制查詢返回結果的數量,從而實現常見的 Top-N 查詢和分頁查詢等功能。
📝在 SQL 標準中,定義了
FETCH
子句實現查詢結果數量的限制。如果使用 Oracle、SQL Server 或者 PostgreSQL,可能會見到這種語法。
11.1 LIMIT 子句
在查詢語句中使用LIMIT
子句的語法如下:
SELECT col1, col2, ...
FROM table_name
[WHERE conditions]
[ORDER BY ...]
LIMIT [off_set,] row_count;
其中,
- off_set 指定一個行偏移量,從第 off_set + 1 行開始返回數據。默認值爲 0,表示從第一行開始返回。
- row_count 指定返回記錄的上限數量。
這兩個參數都必須是大於等於 0 的整數。例如,以下查詢返回了 10 位員工的信息:
select emp_name, sex
from employee
limit 10;
emp_name|sex |
---------|----|
劉備 |男 |
關羽 |男 |
張飛 |男 |
諸葛亮 |男 |
黃忠 |男 |
魏延 |男 |
孫尚香 |女 |
孫丫鬟 |女 |
趙雲 |男 |
廖化 |男 |
除了以上語法形式的LIMIT
子句之外,MySQL 也支持以下寫法(兼容 PostgreSQL):
LIMIT row_count OFFSET off_set
因此,上面的示例也可以寫成:
select emp_name, sex
from employee
limit 10 offset 0;
一般而言,LIMIT
子句很少單獨使用,而是和ORDER BY
子句一起返回更有意義的數據。
11.2 Top-N 查詢
Top-N 查詢通常用於返回按照指定規則排序之後的前 N 條記錄,例如銷售排行榜。
以下查詢用於獲取最先入職的前 5 名員工:
select emp_name, hire_date
from employee
order by hire_date
limit 5;
emp_name |hire_date |
----------|----------|
劉備 |2000-01-01|
關羽 |2000-01-01|
張飛 |2000-01-01|
孫尚香 |2002-08-08|
孫丫鬟 |2002-08-08|
執行該語句時,先按照 hire_date 從早到晚進行排序;然後通過LIMIT
子句限制返回前 5 條記錄。如果將 hire_date 降序排序,可以獲取到目前爲止最後入職的 5 名員工。
⚠️這種返回 Top-N 的方式存在一個侷限性,就是如果最後有多條記錄排名相同,只能隨機選擇其中一些數據返回。這個問題我們可以利用窗口函數解決,在後續文章中會介紹 MySQL 8.0 新增的窗口函數。
11.3 分頁查詢
在應用程序的前端頁面中,通常不會直接顯示全部數據,而是採用分頁顯示的方式。下圖是我的 CSDN 博客關注列表:
首先會返回一個記錄總數,然後每頁顯示 15 條記錄,並且提供“上一頁”、“下一頁”等跳轉功能。返回總數的方法就是使用 COUNT(*) 函數,例如:
select count(*)
from employee;
count(*)|
--------|
25|
員工表中總共有 25 條記錄,COUNT(*) 屬於聚合函數,我們在後續文章中將會進行介紹。
然後就是通過LIMIT
子句獲取指定頁碼中對應的數據,實現的方法就是排序後跳過指定的行數,再返回 Top-N 記錄。假如我們需要按照月薪從高到低顯示員工信息,每頁顯示 10 條記錄;意味着最多需要 3 頁。以下查詢可以用於返回第 3 頁的數據(第 21 到第 25 條記錄):
select emp_id,emp_name, sex, hire_date,salary
from employee
order by salary desc
limit 20, 10;
emp_id|emp_name |sex |hire_date |salary |
------|---------|----|----------|-------|
22|糜竺 |男 |2018-03-27|4300.00|
21|黃權 |男 |2018-03-14|4200.00|
19|龐統 |男 |2017-06-06|4100.00|
20|蔣琬 |男 |2018-01-28|4000.00|
23|鄧芝 |男 |2018-11-11|4000.00|
由於第 3 頁是最後一頁,返回的結果數量只有 5 條。
對於應用程序而言,傳遞給數據庫的參數 off_set 等於(頁碼 - 1)乘以每頁顯示的記錄數,參數 row_count 就是每頁顯示的記錄數。
11.4 返回指定名次
基於分頁查詢的實現,我們還可以獲取指定名次的數據,也就是第 N 行數據。例如,以下查詢返回了銷售部獎金第 2 高的員工:
select emp_id,emp_name, bonus
from employee
where dept_id = 5
order by bonus desc
limit 1, 1;
emp_id|emp_name |bonus |
------|----------|-------|
19|龐統 |2000.00|
銷售部所有員工按照獎金從高到低的排名結果如下:
select emp_id,emp_name, bonus
from employee
where dept_id = 5
order by bonus desc;
emp_id|emp_name |bonus |
------|----------|-------|
18|法正 |5000.00|
19|龐統 |2000.00|
20|蔣琬 |1500.00|
21|黃權 | |
22|糜竺 | |
23|鄧芝 | |
24|簡雍 | |
25|孫乾 | |