db2分页sql_停止尝试使用内部DB框架模拟SQL OFFSET分页!

db2分页sql

我敢肯定,到目前为止,您已经以多种方式弄错了。 而且您可能很快将无法正确处理。 那么,当您可以实施业务逻辑时,为什么还要在SQL调整上浪费您的宝贵时间呢?

让我解释…

直到最近的SQL:2008标准 ,MySQL用户才知道的LIMIT .. OFFSET被标准化为以下简单语句:

SELECT * 
FROM BOOK 
OFFSET 2 ROWS 
FETCH NEXT 1 ROWS ONLY

是。 关键字太多了。

Nv9Oixa

SQL确实是一种非常冗长的语言。 就个人而言,我们真的很喜欢MySQL / PostgreSQLLIMIT .. OFFSET子句的简洁性,这就是为什么我们为jOOQ DSL API选择它的原因 。

在SQL中:

SELECT * FROM BOOK LIMIT 1 OFFSET 2

在jOOQ中:

select().from(BOOK).limit(1).offset(2);

现在,当您是SQL框架供应商时,或者在滚动自己的内部SQL抽象时,您可能会考虑标准化此简洁的小子句。 这是数据库中固有支持偏移分页的两种口味:

-- MySQL, H2, HSQLDB, Postgres, and SQLite
SELECT * FROM BOOK LIMIT 1 OFFSET 2-- CUBRID supports a MySQL variant of the 
-- LIMIT .. OFFSET clause
SELECT * FROM BOOK LIMIT 2, 1-- Derby, SQL Server 2012, Oracle 12, SQL:2008
SELECT * FROM BOOK 
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY-- Ingres. Eek, almost the standard. Almost!
SELECT * FROM BOOK 
OFFSET 2 FETCH FIRST 1 ROWS ONLY-- Firebird
SELECT * FROM BOOK ROWS 2 TO 3-- Sybase SQL Anywhere
SELECT TOP 1 ROWS START AT 3 * FROM BOOK-- DB2 (without OFFSET)
SELECT * FROM BOOK FETCH FIRST 1 ROWS ONLY-- Sybase ASE, SQL Server 2008 (without OFFSET)
SELECT TOP 1 * FROM BOOK

到目前为止,一切都很好。 这些都可以处理。 一些数据库将偏移量放在限制之前,另一些数据库则将限制放在偏移量之前,并且T-SQL系列将整个TOP子句放在SELECT列表之前。 这很容易模仿。 现在呢:

  • Oracle 11g及以下
  • SQL Server 2008及更低版本
  • 具有偏移量的DB2

( 请注意,您可以在DB2中启用各种替代语法 )

当您使用google搜索时,您会发现数百万种方法可以在那些较旧的数据库中模拟OFFSET .. FETCH 。 最佳解决方案始终涉及:

  • 在Oracle中使用带有ROWNUM筛选的双嵌套派生表
  • 在SQL Server和DB2中使用带有ROW_NUMBER()筛选的单嵌套派生表格

因此,您正在模仿它。

xqBjBrO

您认为您会做对吗?

让我们来解决一些您可能没有想到的问题。

首先,Oracle。 Oracle显然想创建一个最大的供应商锁定,只有苹果最近推出了Swift才超过了。 这就是为什么ROWNUM解决方案的性能最佳,甚至优于基于SQL:2003标准窗口函数的解决方案的原因。 不相信吗? 阅读有关Oracle偏移分页性能的这篇非常有趣的文章 。

因此,Oracle中的最佳解决方案是:

-- PostgreSQL syntax:
SELECT ID, TITLE 
FROM BOOK 
LIMIT 1 OFFSET 2-- Oracle equivalent:
SELECT *
FROM (SELECT b.*, ROWNUM rnFROM (SELECT ID, TITLEFROM BOOK) bWHERE ROWNUM <= 3 -- (1 + 2)
)
WHERE rn > 2

那真的等效吗?

当然不是。 您正在选择其他列,即rn列。 在大多数情况下,您可能并不在意,但是如果您想进行有限的子查询以与IN谓词一起使用怎么办?

-- PostgreSQL syntax:
SELECT *
FROM BOOK
WHERE AUTHOR_ID IN (SELECT IDFROM AUTHORLIMIT 1 OFFSET 2
)-- Oracle equivalent:
SELECT *
FROM BOOK
WHERE AUTHOR_ID IN (SELECT * -- Ouch. These are two columns!FROM (SELECT b.*, ROWNUM rnFROM (SELECT IDFROM AUTHOR) bWHERE ROWNUM <= 3)WHERE rn > 2
)

因此,如您所见,您将不得不执行一些更复杂SQL转换。 如果您要手动模拟LIMIT .. OFFSET ,则可以将ID列修补到子查询中:

SELECT *
FROM BOOK
WHERE AUTHOR_ID IN (SELECT ID -- betterFROM (SELECT b.ID, ROWNUM rn -- betterFROM (SELECT IDFROM AUTHOR) bWHERE ROWNUM <= 3)WHERE rn > 2
)

所以,更像是吧? 但是,由于您不是每次都手动编写此代码,因此您将开始创建自己的漂亮的内部SQL框架,该框架涵盖到目前为止所遇到的2-3个用例,对吗?

你能行的。 因此,您将自动regex-search-replace列名以产生上述内容。

所以现在,对吗?

当然不是! 因为您可以在顶级SELECT包含不明确的列名,但不能在嵌套选择中包含。 如果要这样做:

-- PostgreSQL syntax:
-- Perfectly valid repetition of two ID columns
SELECT BOOK.ID, AUTHOR.ID
FROM BOOK
JOIN AUTHOR
ON BOOK.AUTHOR_ID = AUTHOR.ID
LIMIT 1 OFFSET 2-- Oracle equivalent:
SELECT *
FROM (SELECT b.*, ROWNUM rnFROM (-- Ouch! ORA-00918: column ambiguously definedSELECT BOOK.ID, AUTHOR.IDFROM BOOKJOIN AUTHORON BOOK.AUTHOR_ID = AUTHOR.ID) bWHERE ROWNUM <= 3
)
WHERE rn > 2

不。 而且,由于您有多个ID实例,因此手动修补前面示例中的ID列的技巧不起作用。 并且将列重命名为随机值是很麻烦的,因为您自己的内部数据库框架的用户希望接收定义良好的列名称。 即ID和… ID

因此,解决方案是将列重命名两次。 在每个派生表中一次:

-- Oracle equivalent:
-- Rename synthetic column names back to original
SELECT c1 ID, c2 ID
FROM (SELECT b.c1, b.c2, ROWNUM rnFROM (-- synthetic column names hereSELECT BOOK.ID c1, AUTHOR.ID c2FROM BOOKJOIN AUTHORON BOOK.AUTHOR_ID = AUTHOR.ID) bWHERE ROWNUM <= 3
)
WHERE rn > 2

但是现在,我们完成了吗?

当然不是! 如果您将这样的查询加倍嵌套怎么办? 您是否考虑将ID列重命名为合成名称,然后再重新命名? ……让我们留在这里,谈论完全不同的事情:

SQL Server 2008是否可以使用相同的功能?

当然不是! 在SQL Server 2008中,最流行的方法是使用窗口函数。 即ROW_NUMBER() 。 因此,让我们考虑:

-- PostgreSQL syntax:
SELECT ID, TITLE 
FROM BOOK 
LIMIT 1 OFFSET 2-- SQL Server equivalent:
SELECT b.*
FROM (SELECT ID, TITLE, ROW_NUMBER() OVER (ORDER BY ID) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3

就这样吧?

当然不是!

好的,我们已经遇到了这个问题。 我们不应该选择* ,因为在我们将其用作IN谓词的子查询的情况下,这会生成过多的列。 因此,让我们考虑使用综合列名称的正确解决方案:

-- SQL Server equivalent:
SELECT b.c1 ID, b.c2 TITLE
FROM (SELECT ID c1, TITLE c2,ROW_NUMBER() OVER (ORDER BY ID) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3

但是现在我们明白了,对不对?

做出有根据的猜测: 不!

如果您在原始查询中添加ORDER BY子句,会发生什么情况?

-- PostgreSQL syntax:
SELECT ID, TITLE 
FROM BOOK 
ORDER BY SOME_COLUMN
LIMIT 1 OFFSET 2-- Naive SQL Server equivalent:
SELECT b.c1 ID, b.c2 TITLE
FROM (SELECT ID c1, TITLE c2,ROW_NUMBER() OVER (ORDER BY ID) rnFROM BOOKORDER BY SOME_COLUMN
) b
WHERE rn > 2 AND rn <= 3

现在,这在SQL Server中不起作用。 子查询不允许具有ORDER BY子句,除非它们也具有TOP子句(或SQL Server 2012中的OFFSET .. FETCH子句)。

好的,我们可以使用TOP 100 PERCENT进行调整,以使SQL Server满意。

-- Better SQL Server equivalent:
SELECT b.c1 ID, b.c2 TITLE
FROM (SELECT TOP 100 PERCENTID c1, TITLE c2,ROW_NUMBER() OVER (ORDER BY ID) rnFROM BOOKORDER BY SOME_COLUMN
) b
WHERE rn > 2 AND rn <= 3

现在,根据SQL Server,这是正确SQL,尽管您不能保证在查询执行后派生表的顺序将继续存在。 很可能是由于某种影响再次改变了顺序。

如果要在外部查询中按SOME_COLUMN进行排序, SOME_COLUMN必须再次转换SQL语句以添加另一个综合列:

-- Better SQL Server equivalent:
SELECT b.c1 ID, b.c2 TITLE
FROM (SELECT TOP 100 PERCENTID c1, TITLE c2,SOME_COLUMN c99,ROW_NUMBER() OVER (ORDER BY ID) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3
ORDER BY b.c99

确实开始变得有点讨厌。 让我们猜一下是否:

这是正确的解决方案!

当然不是! 如果原始查询中包含DISTINCT怎么办?

-- PostgreSQL syntax:
SELECT DISTINCT AUTHOR_ID
FROM BOOK 
LIMIT 1 OFFSET 2-- Naive SQL Server equivalent:
SELECT b.c1 AUTHOR_ID
FROM (SELECT DISTINCT AUTHOR_ID c1,ROW_NUMBER() OVER (ORDER BY AUTHOR_ID) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3

现在,如果一位作家写了几本书怎么办? 是的, DISTINCT关键字应该删除这些重复项,并且有效地,PostgreSQL查询将首先正确删除重复项,然后应用LIMITOFFSET

但是, ROW_NUMBER()谓词 DISTINCT可以再次删除它们之前总是生成不同的行号。 换句话说, DISTINCT无效。

幸运的是,我们可以使用以下巧妙的小技巧再次调整此SQL :

-- Better SQL Server equivalent:
SELECT b.c1 AUTHOR_ID
FROM (SELECT DISTINCT AUTHOR_ID c1,DENSE_RANK() OVER (ORDER BY AUTHOR_ID) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3

在此处阅读有关此技巧的更多信息:

SQL技巧:row_number()是SELECT,而density_rank()是SELECT DISTINCT 。

请注意, ORDER BY子句必须包含SELECT字段列表中的所有列。 显然,这会将SELECT DISTINCT字段列表中可接受的列限制为窗口函数的ORDER BY子句中允许的列(例如,没有其他窗口函数)。

我们当然也可以尝试使用通用表表达式来解决此问题,或者我们考虑

另一个问题?

当然是!

您甚至不知道窗口函数的ORDER BY子句中的列应该是什么? 您是否刚刚随机选择了任何一栏? 如果该列上没有索引该怎么办,您的窗口函数仍会执行吗?

当原始的SELECT语句还具有ORDER BY子句时,答案很容易,那么您应该采用该子句(如果适用,还要加上SELECT DISTINCT子句中的所有列)。

但是,如果您没有任何ORDER BY子句怎么办?

还有另一把戏! 使用“常量”变量:

-- Better SQL Server equivalent:
SELECT b.c1 AUTHOR_ID
FROM (SELECT AUTHOR_ID c1,ROW_NUMBER() OVER (ORDER BY @@version) rnFROM BOOK
) b
WHERE rn > 2 AND rn <= 3

是的,您需要使用一个变量,因为在SQL Server的那些ORDER BY子句中不允许使用常量。 痛苦的,我知道。

在此处阅读有关此@@ version技巧的更多信息 。

我们完成了吗?

可能不是! 但是,我们可能已经涵盖了大约99%的常见案例和边缘案例。 现在,我们可以睡个好觉了。

注意,所有这些SQL转换都是在jOOQ中实现的。 jOOQ是唯一认真对待SQL(带有所有缺点和警告)SQL抽象框架,它对所有这些疯狂行为进行了标准化。

如开头所述,使用jOOQ,您只需编写:

// Don't worry about general emulation
select().from(BOOK).limit(1).offset(2);// Don't worry about duplicate column names
// in subselects
select(BOOK.ID, AUTHOR.ID)
.from(BOOK)
.join(AUTHOR)
.on(BOOK.AUTHOR_ID.eq(AUTHOR.ID))
.limit(1).offset(2);// Don't worry about invalid IN predicates
select()
.from(BOOK)
.where(BOOK.AUTHOR_ID).in(select(AUTHOR.ID).from(AUTHOR).limit(1).offset(2)
);// Don't worry about the ROW_NUMBER() vs.
// DENSE_RANK() distinction
selectDistinct(AUTHOR_ID).from(BOOK).limit(1).offset(2);

使用jOOQ,您可以像编写PostgreSQL一样出色地编写Oracle SQL或Transact SQL! …不必完全跳起SQL船 ,而是继续使用JPA。

jooq在Java中编写SQL的最佳方法

键集分页

现在,当然,如果您正在阅读我们的博客或我们的合作伙伴博客SQL Performance Explained ,那么现在您应该知道, OFFSET分页通常首先是一个不好的选择。 您应该知道,键集分页几乎总是优于OFFSET分页。

在此处,了解jOOQ如何使用SEEK子句原生支持键集分页 。

翻译自: https://www.javacodegeeks.com/2014/06/stop-trying-to-emulate-sql-offset-pagination-with-your-in-house-db-framework.html

db2分页sql

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

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

相关文章

关于单纤与双纤光端机的区别介绍

单纤和双纤的光端机最大区别就是它们主板上的光模块区别&#xff0c;其他的地方基本上都是一样的。下面&#xff0c;飞畅科技的小编来为大家详细介绍下单纤与双纤光端机的区别&#xff0c;一起来看看吧&#xff01; 单纤光端机&#xff1a;接收与发送的数据在一根光纤上传输。…

ImportError: cannot import name ‘constants‘

运行ns3gym案例一直报这个错&#xff0c;然后重新配置了两遍环境&#xff0c;然而并没有什么用。通过Google Baidu搜索&#xff0c;建议执行以下代码 pip install --upgrade pyzmq 执行后出现以下错误 然后搜索执行代码 sudo pip3 install --ignore-installed pyzmq 安装成功…

如何在不同的浏览器中设置Selenium网格以并行执行

到目前为止&#xff0c;Selenium是最常用的Web自动化测试工具。 如此受欢迎的原因之一是Selenium的自动跨浏览器测试功能。 硒自动化测试可以帮助您在所有主要浏览器&#xff0c;所有主要操作系统甚至移动设备浏览器上进行测试。 您可以在所有功能测试中获得广泛的浏览器覆盖&a…

网管型工业交换机和 非网管型工业交换机的优缺点

工业交换机专业为达到灵便变化多端的工业生产运用要求而设计方案&#xff0c;出示一种性价比高电力线通信通讯解决方法。而工业交换机也分成网管型和非网管型二种。那么&#xff0c;网管型工业交换机和非网管型工业交换机有什么不同&#xff0c;大家该如何选择呢&#xff1f;接…

如何集成和使用EclEmma插件来获得良好的Junit覆盖率

你好朋友&#xff0c; 如果编写好的代码很重要&#xff0c;那么编写覆盖所有业务逻辑的优良Junit测试用例也同样重要。通过编写覆盖业务逻辑的Junit测试用例&#xff0c;我们实际上确保代码的每种方法都能正常工作按照预期进行&#xff0c;因此减少了在软件开发的后期阶段中获…

工业4.0时代,工业交换机在智能电网建设中有什么作用?

随着工业以太网技术、光纤技术和信息处理技术的发展&#xff0c;并向电力行业的渗透&#xff0c;在当前技术条件支持下&#xff0c;工业以太网通信在运行过程中表现出高可靠性、灵活性和扩展性等优点&#xff0c;对优化整个电网系统设备元件之间的连接和信息传输有着重要的作用…

工业交换机的性能优势有哪些?

工业交换机也称作工业以太网交换机&#xff0c;即应用于工业控制领域的以太网交换机设备&#xff0c;对工业交换机我们有多少人了解呢&#xff1f;究竟何为工业交换机&#xff0c;工业交换机有哪些功能呢&#xff1f;接下来就由飞畅科技的小编来为大家详细讲解下吧&#xff01;…

谷歌浏览器出现“远程计算机访问失败问题”

转载链接 一、进入浏览器设置 二、“internet选项”目录 三、设置 只勾选一个&#xff0c;其余均不选。 四、打开新网页&#xff0c;解决问题

工业交换机都有哪些优势,该如何挑选

相对普通交换机而言&#xff0c;工业交换机在普通交换机的基础之上加强了功能&#xff0c;端口配置和产品系列更加丰富和灵活&#xff0c;能够满足各种工业领域的需求。广泛应用于智慧交通、安防监控、风电光伏、煤矿等领域。尤其是电力、交通、冶金被称为工业交换机应用的三大…

用Java中的抽象类扩展抽象类

示例问题 当我创建Java :: Geci抽象类AbstractFieldsGenerator和AbstractFilteredFieldsGenerator我遇到了一个不太复杂的设计问题。 我想强调一下&#xff0c;对于某些人来说&#xff0c;这个问题和设计可能看起来很明显&#xff0c;但是在我最近与一位初级开发人员&#xff0…

工业交换机与工业路由器的区别

工业交换机&#xff08;也叫工业以太网交换机&#xff09;&#xff0c;即应用于工业控制领域的以太网交换机设备&#xff0c;由于采用的网络标准&#xff0c;其开放性好、应用广泛以及价格低廉、使用的是透明而统一的TCP/IP协议&#xff0c;以太网已经成为工业控制领域的主要通…

Sublime介绍安装和使用(转载)

转载&#xff1a; 原文链接&#xff1a;https://blog.csdn.net/ITTechnologyHome/article/details/80486235 1.1 Sublime介绍 Sublime是一款跨平台、收费的文件编辑器&#xff0c;可以用来编写HTML,CSS,JavaScript,PHP等应用程序。 1.2 Sublime特点 跨平台,支持主流操作系统…

工业交换机在城市智慧轨道交通中的应用分析

俗话说&#xff0c;城市建设&#xff0c;交通先行&#xff0c;轨道交通是解决“城市病”的一把金钥匙&#xff0c;而智慧交通更是建设智慧城市的重要构成部分。从2009年开始&#xff0c;我国就逐渐进入城市轨道交通建设的高潮&#xff0c;并逐年扩大地铁市场。发展以轨道交通为…

apache hive_Hive:使用Apache Hive查询客户最喜欢的搜索查询和产品视图计数

apache hive这篇文章介绍了如何使用Apache Hive查询Hadoop下存储的搜索点击数据。 我们将以示例的形式生成有关总产品浏览量的客户最爱搜索查询和统计信息。 继续之前的文章 使用大数据分析客户产品搜索点击次数 &#xff0c; Flume&#xff1a;使用Apache Flume收集客户产品…

工业交换机在工业通信领域的应用分析

工业交换机是专门为满足灵活多变的工业应用需求而设计&#xff0c;提供一种高性价比工业以太网通讯解决方案。工业交换机&#xff0c;作为我们广为使用的局域网硬件设备&#xff0c;一直为大家所熟悉。它的普及程度其实是由于以太网的广泛使用&#xff0c;作为今天以太网的主流…

工业以太网交换机都有哪些作用

工业以太网交换机由于使用及定位的关系&#xff0c;区别于商业交换机&#xff0c;它更关注稳定性&#xff0c;耐高温&#xff0c;耐振动&#xff0c;耐腐蚀等一些工业特性。工业以太网交换机以其较高的防护等级&#xff08;一般IP40)、较强的电磁兼容性&#xff08;EMS 4级&…

光纤交换机是什么,光纤交换机的作用是什么?

随着网络的发展&#xff0c;先后出现了交换机、路由器、电话光端机等网络设备&#xff0c;在数据存储网络中&#xff0c;光纤交换机起到了重要的作用。今天飞畅科技的小编来为大家介绍下光纤交换机及光纤交换机的作用&#xff0c;一起来看看吧&#xff01; 光纤交换机的简介 光…

光纤交换机产品功能介绍

光纤交换机是一种高速的网络传输中继设备&#xff0c;又叫做光纤通道交换机、SAN交换机&#xff0c;光纤传输的优点是速度快、抗干扰能力强。那么&#xff0c;光纤交换机有哪些功能呢&#xff1f;接下来我们就跟随飞畅科技的小编一起来看看吧&#xff01; 通道协议支持 SAN交换…

光纤交换机光纤通道协议介绍

光纤通道&#xff08;FC&#xff0c;Fibre Channel&#xff09;协议是美国国家标准所指定的一种串行高速、低延时、低误码的标准协议能够为存储设备、IP 数据网、音频流等应用提供高速数据传输的骨干网络技术。随着光纤通道在不同领域的应用&#xff0c;在光纤通道协议的基础上…

POI创建的文档具有不同条件的灵活样式

介绍 这篇文章解释了基于各种标准将样式应用于文档的困难并提供了解决方案。 Java编程中的常见任务之一是根据存储在数据库中的数据创建Excel报告。 在这些情况下&#xff0c;Java程序员使用POI :-)。 这些报告通常具有严格的样式和数据格式规则。 数据通常是SQL查询执行的结果…