关于常见数据库中SQL分页语法整理

news2024/10/9 15:38:08

标题

  • MySQL分页查询
    • 常规版
    • 升级版
  • Oracle分页查询
    • 常规版
    • 升级版
  • PostgreSQL分页查询
    • 常规版
    • 升级版
  • SQL Server分页查询
    • 常规版
    • 升级版

MySQL分页查询

在MySQL中,分页查询通常使用 LIMIT 关键字来实现。
LIMIT [offset,] rows 其中,offset表示偏移量(从结果集的第几行开始返回,默认从 0 开始计数),rows表示要返回的行数。

常规版

# 查询第一页(假设每页显示 10 条记录):
SELECT * FROM users LIMIT 0, 10; 
#这里0是偏移量,表示从第 1 行(偏移量为 0)开始,10是要返回的行数。

#查询第二页:
SELECT * FROM users LIMIT 10, 10;
#此时偏移量为10,即跳过前面 10 行,然后返回 10 行。

升级版

更灵活的分页查询
如果你需要更灵活地处理分页,可以使用变量来动态设置 offset 和 rows:

SET @page_size := 10;
SET @page_number := 2;
SET @offset := (@page_size * (@page_number - 1));

SELECT *
FROM employees
LIMIT @offset, @page_size;



# 在存储过程中使用 LIMIT 进行分页查询,以下是一个简单的存储过程示例,用于实现分页查询:
   DELIMITER $$
   CREATE PROCEDURE get_page(IN page_number INT, IN page_size INT)
   BEGIN
       SET @offset = (page_number - 1) * page_size;
       SET @limit = page_size;
       SET @sql = CONCAT('SELECT * FROM your_table LIMIT ', @offset, ', ', @limit);
       PREPARE stmt FROM @sql;
       EXECUTE stmt;
       DEALLOCATE PREPARE stmt;
   END$$
   DELIMITER ;

使用 JOIN 或子查询进行分页
有时候,你可能需要在复杂的查询中进行分页,例如包含 JOIN 或子查询:

SELECT e.*
FROM employees e
JOIN (
    SELECT employee_id
    FROM employees
    ORDER BY hire_date
    LIMIT @offset, @page_size
) as sub_query ON e.employee_id = sub_query.employee_id;

MySQL 8.0 引入了窗口函数,可以使用 ROW_NUMBER() 来实现分页:

SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY hire_date) as row_num
    FROM employees
) as paginated_results
WHERE row_num BETWEEN @offset + 1 AND @offset + @page_size;

Oracle分页查询

在Oracle数据库中,分页查询通常使用ROWNUM伪列或者数据库12c及更高版本中的FETCH FIRSTOFFSET子句来实现。

常规版

在Oracle 12c之前的版本,分页查询通常依赖于ROWNUM伪列。ROWNUM为结果集中的每一行分配一个唯一的行号。

SELECT * FROM (
  SELECT temp.*, ROWNUM rnum FROM (
    SELECT * FROM your_table WHERE conditions ORDER BY some_column
  ) temp WHERE ROWNUM <= :upper_bound
) WHERE rnum > :lower_bound;
# :upper_bound是上界值,通常是(页码 * 每页显示的行数)。
# :lower_bound是下界值,通常是(页码 - 1) * 每页显示的行数 + 1。

# 假设你有一个名为employees的表,你想查询第2页的数据,每页显示10行数据。
SELECT * FROM (
  SELECT temp.*, ROWNUM rnum FROM (
    SELECT * FROM employees ORDER BY employee_id
  ) temp WHERE ROWNUM <= 20
) WHERE rnum > 10;

在这里插入图片描述

Oracle 12c及更高版本使用OFFSET和FETCH进行分页

SELECT *
FROM your_table
WHERE conditions
ORDER BY some_column
OFFSET :lower_bound ROWS FETCH NEXT :page_size ROWS ONLY;
# :lower_bound是分页的起始行,通常是(页码 - 1) * 每页显示的行数。
# :page_size是每页显示的行数。

# 假设你有一个名为employees的表,你想查询第2页的数据,每页显示10行数据。
SELECT *
FROM employees
ORDER BY employee_id
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
# 这里,OFFSET 10 ROWS跳过前10行,FETCH NEXT 10 ROWS ONLY则返回接下来的10行。

在这里插入图片描述

升级版

动态分页查询
有时候我们可能需要根据用户输入或者业务逻辑动态地确定每页显示的记录数和页码。
例如,假设我们有一个存储过程,接受两个参数:p_page_number(页码)和p_page_size(每页记录数)。

在这个存储过程中,首先计算偏移量v_offset,然后在内部子查询中使用分析函数ROW_NUMBER()对表中的数据按照some_column(根据实际需求替换为排序依据的列)进行排序和编号。接着在中层子查询中根据计算得到的偏移量和每页记录数限制ROWNUM,最后在外层子查询中根据rn(行号)筛选出真正需要的页面数据。

   CREATE OR REPLACE PROCEDURE dynamic_paging(p_page_number IN NUMBER, p_page_size IN NUMBER) AS
       v_offset NUMBER := (p_page_number - 1) * p_page_size;
   BEGIN
       -- 使用分析函数和ROWNUM进行分页
       SELECT *
       FROM (
           SELECT t.*, ROWNUM rn
           FROM (
               SELECT col1, col2, col3, -- 这里列出实际表中的列
                   -- 使用分析函数(例如ROW_NUMBER)对数据进行排序和编号
                   ROW_NUMBER() OVER (ORDER BY some_column) AS row_num
               FROM your_table
           ) t
           WHERE ROWNUM <= v_offset + p_page_size
       )
       WHERE rn > v_offset;
   END;

多表连接与分页结合
当查询涉及多个表连接时,分页操作需要考虑连接结果的顺序和数量。
假设有table1和table2两个表,我们要查询连接后的结果并进行分页。

这里先进行table1和table2的连接操作,然后使用ORDER BY对连接结果进行排序,接着在内部子查询中使用ROWNUM进行初步的分页筛选,最后在外层子查询中根据行号rn进行调整以得到正确的第一页数据。对于多表连接的分页查询,确保连接的正确性以及排序的合理性是很重要的,这样才能得到准确的分页结果。

   SELECT *
   FROM (
       SELECT t.*, ROWNUM rn
       FROM (
           SELECT col1, col2, col3 -- 这里列出连接后的列
           FROM table1
           JOIN table2 ON table1.key = table2.key
           ORDER BY some_column
       ) t
       WHERE ROWNUM <= 10
   )
   WHERE rn > 0;

分区表的分页优势
如果数据存储在分区表中,可以利用分区的特性更高效地进行分页查询。
假设我们有一个按照日期分区的表partitioned_table,要查询某个日期分区内的数据并进行分页。

通过指定分区名,可以直接在该分区内进行分页查询,减少了查询的数据量,提高了查询效率,尤其是在处理大型表时这种优势更加明显。

   SELECT *
   FROM (
       SELECT t.*, ROWNUM rn
       FROM (
           SELECT col1, col2, col3
           FROM partitioned_table PARTITION (partition_name) -- 替换为实际分区名
           ORDER BY some_column
       ) t
       WHERE ROWNUM <= 10
   )
   WHERE rn > 0;

PostgreSQL分页查询

在PostgreSQL中,分页查询通常使用 LIMIT 和 OFFSET 子句来实现。这两个子句可以限制查询结果的数量,并指定返回结果的起始点。

常规版

使用 LIMIT 和 OFFSET 关键字

# column_name是用于排序的列(如果不指定排序顺序,分页结果可能会不稳定),
# count 是要返回的行数(即每页的行数),
# offset_value是偏移量(表示从结果集的第几行开始返回)。
SELECT * FROM table_name WHERE condition ORDER BY column_name
LIMIT count OFFSET offset_value;


# 查询第一页(假设每页显示 10 条记录)
# 这里查询users表,按照user_id排序,返回前 10 条记录(偏移量为 0 表示从第一行开始)。
SELECT * FROM users ORDER BY user_id LIMIT 10 OFFSET 0;


# 查询第二页
SELECT * FROM users ORDER BY user_id LIMIT 10 OFFSET 10;

使用 FETCH 和 OFFSET(PostgreSQL 8.4 及以上版本支持 FETCH)

SELECT * FROM your_table ORDER BY some_column OFFSET offset_value FETCH FIRST num_rows ROWS ONLY;

SELECT * FROM users ORDER BY user_id OFFSET 0 FETCH FIRST 10 ROWS ONLY;

SELECT * FROM users ORDER BY user_id OFFSET 10 FETCH FIRST 10 ROWS ONLY;

升级版

更灵活的分页查询

SET @page_size = 10;
SET @page_number = 2;
SET @offset = (@page_size * (@page_number - 1));

SELECT *
FROM employees
ORDER BY employee_id
LIMIT @page_size OFFSET @offset;


# 在这个函数中,根据传入的页码p_page_number和每页大小p_page_size构建动态 SQL 语句。
#然后使用RETURN QUERY EXECUTE执行动态 SQL 并返回结果。这种方式使得分页查询更加灵活,能够适应不同的需求。
CREATE OR REPLACE FUNCTION dynamic_paging(p_page_number INT, p_page_size INT)
    RETURNS SETOF your_table_type AS
$BODY$
DECLARE
    v_sql TEXT;
BEGIN
    v_sql := format('SELECT * FROM your_table ORDER BY some_column LIMIT %s OFFSET %s', p_page_size, (p_page_number - 1) * p_page_size);
    RETURN QUERY EXECUTE v_sql;
END;
$BODY$
LANGUAGE plpgsql;

多表连接后的分页

# 当查询涉及多个表的连接时,分页操作需要考虑连接结果集的顺序和结构。
# 例如,假设有三个表table1、table2和table3,要对它们连接后的结果进行分页:
   SELECT *
   FROM (
       SELECT sub.*, ROWNUM AS row_num
       FROM (
           SELECT t1.col1, t2.col2, t3.col3
           FROM table1 t1
               JOIN table2 t2 ON t1.key = t2.key
               JOIN table3 t3 ON t2.other_key = t3.other_key
           ORDER BY t1.some_column
       ) sub
   )
   WHERE row_num BETWEEN start_row AND end_row;
#首先在内部子查询中进行多表连接并按照table1中的some_column排序。
#然后在中层子查询中使用ROWNUM(这里ROWNUM类似 Oracle 中的概念,
#在 PostgreSQL 中是自定义的行号)为结果集编号。
#最后在外层子查询中根据计算出的开始行start_row和结束行
#end_row(可以根据页码和每页大小计算得出)进行分页筛选。

使用窗口函数进行分页
PostgreSQL 8.4及以上版本支持窗口函数,可以使用 row_number() 窗口函数来实现更复杂的分页逻辑:

WITH paginated AS (
  SELECT *, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn
  FROM employees
)
SELECT *
FROM paginated
WHERE rn BETWEEN 11 AND 20;


#窗口函数可以在不改变结果集行数的情况下对每一行进行计算,这在复杂的分页场景中很有用。
#例如,假设要对一个包含员工信息的表employees进行分页,并且在分页结果中显示每个员工在部门内的排名:
SELECT department, employee_name, salary,
       ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_in_department
FROM employees
ORDER BY department, rank_in_department
LIMIT page_size OFFSET offset;

# 这里使用ROW_NUMBER()窗口函数计算每个员工在其所属部门内按照薪资降序排列的排名。
# 然后按照部门和部门内排名进行排序,最后进行分页操作。这种方式可以在分页结果中提供更多的信息和分析价值。

SQL Server分页查询

在 SQL Server 中,分页查询可以通过使用 OFFSET 和 FETCH 子句来实现。这些子句在 SQL Server 2012 及更高版本中被引入,提供了一种简单且直观的方式来进行分页。

常规版

使用OFFSET - FETCH子句(SQL Server 2012 及以上版本)

SELECT * FROM your_table ORDER BY some_column OFFSET offset_rows ROWS FETCH NEXT fetch_rows ROWS ONLY;
# 其中,your_table是要查询的表名,
# some_column是用于排序的列(如果不指定排序顺序,分页结果可能会不稳定),
# offset_rows是偏移量(表示从结果集的第几行开始返回),
# fetch_rows是要返回的行数(即每页的行数)。

# 查询第一页(假设每页显示 10 条记录)
SELECT * FROM users ORDER BY user_id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
#  查询第二页
SELECT * FROM users ORDER BY user_id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

使用TOP关键字结合子查询(适用于旧版本)

# 查询第一页(假设每页显示 10 条记录)
SELECT TOP 10 * FROM your_table ORDER BY some_column;
#  查询第二页(假设每页显示 10 条记录)
# 这个方法相对复杂一些,在子查询中获取前 20 条记录,然后通过外部查询排除前 10 条记录来得到第二页的数据。
SELECT * FROM (
    SELECT TOP 20 * FROM your_table ORDER BY some_column
) AS subquery
WHERE NOT EXISTS (SELECT TOP 10 * FROM your_table ORDER BY some_column)
ORDER BY some_column;

升级版

使用动态 SQL 实现灵活分页

# 例如,创建一个存储过程,接受页码@pageNumber和每页行数@pageSize作为参数:
   CREATE PROCEDURE DynamicPaging
       @pageNumber INT,
       @pageSize INT
   AS
   BEGIN
       DECLARE @sql NVARCHAR(MAX);
       SET @sql = N'SELECT * FROM (
                   SELECT *, ROW_NUMBER() OVER (ORDER BY some_column) AS row_num
                   FROM your_table
               ) AS subquery
               WHERE row_num BETWEEN ' + CAST((@pageNumber - 1) * @pageSize + 1 AS NVARCHAR(10)) + ' AND ' + CAST(@pageNumber * @pageSize AS NVARCHAR(10));
       EXEC sp_executesql @sql;
   END;
# 在这个存储过程中,首先构建动态 SQL 语句。使用ROW_NUMBER()函数为结果集中的每一行分配一个行号(按照some_column排序),
# 然后根据传入的页码和每页行数计算出要获取的行号范围,最后通过sp_executesql执行动态 SQL 语句来实现分页查询。

多表连接后的分页

# 例如,假设有表table1和table2,要对它们连接后的结果进行分页:
   SELECT *
   FROM (
       SELECT sub.*, ROW_NUMBER() OVER (ORDER BY some_column) AS row_num
       FROM (
           SELECT t1.col1, t2.col2
           FROM table1 t1
               JOIN table2 t2 ON t1.key = t2.key
           ORDER BY some_column
       ) AS sub
   ) AS final
   WHERE row_num BETWEEN start_row AND end_row;
# 首先在内部子查询中进行table1和table2的连接,并按照some_column排序。
#然后在中层子查询中使用ROW_NUMBER()函数为连接后的结果集分配行号。
#最后在外层子查询中根据计算出的起始行start_row和结束行
#end_row(可以根据页码和每页行数计算得出)进行分页筛选。

与窗口函数结合的分页查询

# 例如,要查询员工表employees中的数据并进行分页,同时显示每个部门内员工的排名:
   SELECT department, employee_name, salary,
          ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_in_department
   FROM employees
   ORDER BY department, rank_in_department
   OFFSET offset_rows ROWS FETCH NEXT fetch_rows ROWS ONLY;
#这里使用ROW_NUMBER()窗口函数在每个部门内按照薪资降序为员工分配排名。
#然后按照部门和部门内排名进行排序,最后再进行分页操作。这种方式可以在分页结果中提供更详细的部门内员工信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199394.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLMUnity:在Unity 3D中使用大模型

在本文中&#xff0c;我们将展示如何在 Unity 引擎中使用 LLM&#xff08;大型语言模型&#xff09;&#x1f3ae;。我们将使用 LLMUnity 包&#xff0c;并查看一些示例&#xff0c;了解如何仅用几行代码设置对话交互&#xff01; 免责声明&#xff1a;我是 LLMUnity 的作者。…

STM32通用定时器TIM3的PWM输出实验配置步骤

通用定时器 PWM 输出实验 本小节我们来学习使用通用定时器的 PWM 输出模式。 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。我们可以让定时…

Linux 命令 netstat 的 10 个基本用法

Netstat 简介 Netstat 是一款命令行工具&#xff0c;可用于列出系统上所有的网络套接字连接情况&#xff0c;包括 tcp, udp 以及 unix 套接字&#xff0c;另外它还能列出处于监听状态&#xff08;即等待接入请求&#xff09;的套接字。如果你想确认系统上的 Web 服务有没有起来…

(RAG)技术结合了大模型(LLM)与内部数据,从而实现更智能且相关性更高的 AI 应用

利用先进的生成式 AI 技术&#xff08;如 RAG&#xff09;&#xff0c;释放数据的潜力&#xff0c;推动创新并获取战略优势 主要功能 使用向量数据库优化数据检索和生成 通过 AI 代理提升决策效率并自动化工作流程 克服实施真实 RAG 系统中的常见挑战 购买印刷版或 Kindle …

【C++】速通涉及 “vector” 的经典OJ编程题

【C】速通涉及 “vector” 的经典OJ编程题 一. 杨辉三角解题思路&#xff1a;代码实现&#xff1a; 二. 删除有序数组中的重复项解题思路&#xff1a;代码实现&#xff1a;【C/C】按位运算符使用规制 三. 只出现一次的数字解题思路&#xff1a;代码实现&#xff1a; 四. 只出现…

【D3.js in Action 3 精译_031】3.5.2 DIY实战:在 Observable 平台实现带数据标签的 D3 条形图并改造单元测试模块

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

PyQt5界面美化教程:一键切换四种风格

PyQt5界面美化教程&#xff1a;一键切换四种风格 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机器视觉&#xff0c;目标检测&#xff0c;图像分类&#xff0c;姿态识别&#x…

【可答疑】基于51单片机的PWM控制智能台灯设计(含仿真、代码、报告、演示视频等)

✨哈喽大家好&#xff0c;这里是每天一杯冰美式oh&#xff0c;985电子本硕&#xff0c;大厂嵌入式在职0.3年&#xff0c;业余时间做做单片机小项目&#xff0c;有需要也可以提供就业指导&#xff08;免费&#xff09;~ &#x1f431;‍&#x1f409;这是51单片机毕业设计100篇…

vue 同一个页面第二次跳转路由内容不更新

问题出现原因 在vue中相同路由之间跳转&#xff0c;默认在跳转路由时会采用缓存策略,并不会刷新当前路由组件。导致mounted&#xff08;初始化&#xff09;,beforeDestory&#xff08;销毁&#xff09;等生命周期钩子函数并不会触发&#xff0c;从而产生路由跳转了&#xff0c;…

一文读懂Spring AOP的工作原理和机制(面试经)

导览 前言AOP(Aspect-Oriented Programming)必学必看1. 核心概念2. 主要原理3. 实践应用3.1 添加maven依赖3.2 定义切面Aspect3.3 定义Methods (join point) 切入点 结语精彩回顾 前言 在上文中&#xff0c;博主介绍了Spring IoC的核心原理和用法&#xff0c;相信你可以通过文…

Aria2Cloudreve任意文件写入到RCE

什么是Aria2 Aria2 是一个轻量级的命令行下载工具&#xff0c;支持多种下载协议&#xff0c;如 HTTP、FTP、SFTP、BitTorrent 和 Metalink。它以其强大的多源下载能力而著称&#xff0c;可以同时从多个服务器或对等节点下载文件&#xff0c;加快下载速度。Aria2 占用资源少&am…

UE4 材质学习笔记05(凹凸偏移和视差映射/纹理压缩设置)

一.凹凸偏移和视差映射 1.偏移映射 这需要一个高度图并且它的分辨率很低&#xff0c;只有256*256&#xff0c;事实上&#xff0c;如果高度图的分辨率比较低并且有点模糊&#xff0c;效果反而会更好 然后将高度图输出到BumpOffset节点的height插槽中&#xff0c; 之后利用得到…

JVM 内存模型与垃圾回收过程详解

JVM 内存模型与垃圾回收过程详解 文章目录 JVM 内存模型与垃圾回收过程详解1. JVM内存分区1.1 具体分区1.2 JVM内存分区的必要性 2. 垃圾回收2.1 CMS垃圾回收器2.2 G1垃圾回收器2.3 JVM垃圾回收从新生代到老年代 1. JVM内存分区 1.1 具体分区 Java虚拟机&#xff08;JVM&#…

YOLOv10改进策略【注意力机制篇】| 蒙特卡罗注意力(MCAttn)模块,提高小目标的关注度

一、本文介绍 本文记录的是基于蒙特卡罗注意力&#xff08;MCAttn&#xff09;模块的YOLOv10目标检测改进方法研究。利用蒙特卡罗注意力&#xff08;MCAttn&#xff09;模块提高RepNCSPELAN4模块的跨尺度特征提取能力&#xff0c;使模型能够更好地传递和融合提取的多尺度特征&…

<Rust>iced库(0.13.1)学习之部件(三十二):使用markdown部件来编辑md文档

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 注:新版本已更新为0.13 概述 这是本专栏的第三十二篇,主要介绍一…

Matlab实现海鸥优化算法优化回声状态网络模型 (SOA-ESN)(附源码)

目录 1.内容介绍 2部分代码 3.实验结果 4.内容获取 1内容介绍 海鸥优化算法&#xff08;Seagull Optimization Algorithm, SOA&#xff09;是一种受海鸥觅食和飞行行为启发的群体智能优化算法。SOA通过模拟海鸥在空中搜寻食物、聚集和分散的行为模式&#xff0c;来探索和开发…

免费ppt模板从哪找?一文看这里

国庆假期结束&#xff0c;回工作岗位的你是不是正忙着准备汇报材料&#xff1f;别担心&#xff0c;一份精美的PPT能为你的工作汇报增色不少。 而一个吸引人的PPT背景模板&#xff0c;更是能让你的演示脱颖而出。 为了帮助你们快速找到高质量免费ppt模板背景&#xff0c;以下特…

C++:string(题目篇)

文章目录 前言一、字符串相加二、仅仅反转字母三、字符串中的第一个唯一字符四、字符串最后一个单词的长度五、检查字符串是否是回文六、反转字符串 II七、反转字符串中的单词 III八、字符串相乘总结 前言 学习了string后&#xff0c;我们来学习对应的习题。 一、字符串相加 …

SWIFT Payment

SWIFT stands for Society for Worldwide Interbank Financial Telecommunication SWIFT——环球银行金融电信协会 SWIFT Payment Useful Link ISO 20022https://www.iso20022.org/https://www.swift.com/standards/iso-20022MT and MX Equivalence Tableshttps://www2.swift…

Python验证码识别——前处理

目前不少系统的验证码做得越来越复杂&#xff0c;人眼都难以识别&#xff0c;尤其是QQ之类的验证码&#xff0c;想要识别&#xff0c;太难了。 现在有这样一个验证码&#xff1a; 一般的验证码识别&#xff0c;都是先进行前处理&#xff0c;然后分割&#xff0c;在进行识别。这…