-- Oracle、SQL Server、PostgreSQL
SELECT emp_name, sex, email
FROM employee
ORDER BY emp_id
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
-- MySQL、PostgreSQL、SQLite
SELECT emp_name, sex, email
FROM employee
ORDER BY emp_id
LIMIT 10 OFFSET 10;
-- Oracle、SQL Server、PostgreSQL
WITH e AS ( -- 初始查询
SELECT emp_id, emp_name, sex, email
FROM employee
),
t AS (
SELECT emp_id, emp_name, sex, email,
COUNT(*) OVER () AS total_rows, -- 总记录数
ROW_NUMBER () OVER (ORDER BY e.emp_id) AS row_nbr -- 偏移量,ORDER BY和初始查询相同
FROM e
ORDER BY e.emp_id -- 排序
OFFSET 10 ROWS -- 分页
FETCH NEXT 10 ROWS ONLY
)
SELECT
emp_id, emp_name, sex, email,
COUNT(*) OVER () AS actual_page_size, -- 当前页实际记录数
CASE MAX(row_nbr) OVER ()
WHEN total_rows THEN 'Y'
ELSE 'N'
END AS last_page, -- 是否最后一页
total_rows, -- 总记录数
row_nbr, -- 每一条数据的偏移量
((row_nbr - 1) / 10) + 1 AS current_page -- 当前所在页码
FROM t
ORDER BY emp_id;
-- MySQL、PostgreSQL、SQLite
WITH e AS ( -- 初始查询
SELECT emp_id, emp_name, sex, email
FROM employee
),
t AS (
SELECT emp_id, emp_name, sex, email,
COUNT(*) OVER () AS total_rows, -- 总记录数
ROW_NUMBER () OVER (ORDER BY e.emp_id) AS row_nbr -- 偏移量,ORDER BY和初始查询相同
FROM e
ORDER BY e.emp_id -- 排序
LIMIT 10
OFFSET 10 ROWS -- 分页
)
SELECT
emp_id, emp_name, sex, email,
COUNT(*) OVER () AS actual_page_size, -- 当前页实际记录数
CASE MAX(row_nbr) OVER ()
WHEN total_rows THEN 'Y'
ELSE 'N'
END AS last_page, -- 是否最后一页
total_rows, -- 总记录数
row_nbr, -- 每一条数据的偏移量
((row_nbr - 1) / 10) + 1 AS current_page -- 当前所在页码
FROM t
ORDER BY emp_id;
首先,我们定义了通用表表达式 e,它是返回数据的初始查询,可以增加其他的过滤条件。
然后,我们基于 e 定义了另一个通用表表达式 t,在定义中进行了排序和分页,并且利用窗口函数 COUNT(*) 计算总的记录数,利用窗口函数 ROW_NUMBER () 计算每条数据的偏移量(行号)。
接下来,我们基于 t 返回了更多的参数,利用窗口函数 COUNT(*) 返回了当前页的实际记录数,通过窗口函数 MAX(row_nbr) 返回的当前页最大偏移量和总记录数的比较判断是否最后一页,以及当前所在的页码。