【SQL开发实战技巧】系列(二十二):数仓报表场景(上) 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
系列文章目录
【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景(上) 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
文章目录
- 系列文章目录
- 前言
- 一、怎样对SQL查询结果集分页比较好
- 二、分析函数的使用限制及Merge用对场景对性能提升非常大
- 三、隔行抽样
- 总结
前言
本篇文章讲解的主要内容是:怎样对SQL查询结果集分页比较好、平时你用分析函数优化传统查询,所以你会不会认为分析函数一定比传统查询效率高?一个实验告诉你答案、我想对数据进行隔行抽样应该怎么实现?
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。
一、怎样对SQL查询结果集分页比较好
工作中我们为了便于查询网页中的数据,经常会对从数据库查询到的结果集进行分页显示。
比如我现在有一个需求:
要求员工表(EMP的数据)按工资排序后一次只显示5行数据,下次再显示接下来的5行。
下面以第二页数据(6到10行)为例进行分页。
前面已讲过,要先排序,然后在外层才能生成正确的序号:
SQL> with t as/*先排序*/2 (select sal, ename from emp where sal is not null order by sal),3 t1 as/*取得排序后的序号,并过滤掉10行以后的数据*/4 (select rownum as rn, sal, ename from t where rownum <= 10)/*根据前面生成的序号过滤掉6行以前的数据*/5 select * from t1 where rn >= 66 ;RN SAL ENAME
---------- --------- ----------6 1300.00 MILLER7 1500.00 TURNER8 1600.00 ALLEN9 2450.00 CLARK10 2850.00 BLAKESQL>
可能有朋友会感觉我这么嵌套的有点麻烦,我列举一下你们想的:
- 为什么不直接在内层应用条件
WHERE rownum<=10
呢?
下面对比一下rownum的结果。
SQL> select rownum rnn,aa.*2 from (3 select rownum as rn ,sal, ename from emp where deptno=20 and sal is not null4 order by sal5 ) aa;RNN RN SAL ENAME
---------- ---------- --------- ----------1 1 800.00 SMITH2 4 1100.00 ADAMS3 2 2975.00 JONES4 5 3000.00 FORD5 3 3000.00 SCOTTSQL>
可以看到,内层直接生成的rownum(rn)
与sal的顺序不一样,要想得到正确的顺序就要先排序后取序号。
- 为什么不直接用
rownum<=10 and rownum>=6
,而要分开写呢?
下面来看一下。
SQL> select * from emp where rownum>=6 and rownum <=10;EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------SQL>
如前面博客所述,因为rownum是一个伪列,需要取出数据后,rownum才会有值,在执行where rownum>=6
时,因为始终没取前10条数据出来,所以这个条件就查询不到数据,需要先在子查询中取出数据,然后外层用WHERE rn >=6
来过滤。
你也可以先用row_number()生成序号,再过滤,这样就只需要嵌套一次。
SQL>
SQL> select aa.*2 from (3 select row_number()over(order by sal) as rn ,sal, ename from emp where sal is not null4 order by sal5 ) aa6 where rn >=6 and rn<=10;RN SAL ENAME
---------- --------- ----------6 1300.00 MILLER7 1500.00 TURNER8 1600.00 ALLEN9 2450.00 CLARK10 2850.00 BLAKESQL>
这个语句比较简单,但因为分页语句的特殊性,在调用PLAN时可能会受到分析函数的影响,有些索引或PLAN(如:first_rows)不能用。所以,在此建议大家使用第一种分页方式,把第一种分页方式当作模板,然后套用。
二、分析函数的使用限制及Merge用对场景对性能提升非常大
现有数据如下:
CREATE TABLE hotel(floor_nbr,room_nbr)AS
SELECT 1,100 FROM dual UNION ALL
SELECT 1,100 FROM dual UNION ALL
SELECT 2,100 FROM dual UNION ALL
SELECT 2,100 FROM dual UNION ALL
SELECT 3,100 FROM dual;
现在有个需求:将floor_nbr编号更新为类似:101、102、201、202的数据。
我们可以用row_number重新生成编号,或许马上会有读者想到UPDATE语句。让我们来执行一下。
SQL> update hotel set room_nbr =(floor_nbr*100+row_number()over(partition by floor_nbr order by floor_nbr));
update hotel set room_nbr =(floor_nbr*100+row_number()over(partition by floor_nbr order by floor_nbr))ORA-30483: window 函数在此禁用SQL>
有人想用“可更新VIEW",语句如下:
SQL> update (2 select rowid as rid,room_nbr,(floor_nbr*100+row_number()over(partition by floor_nbr order by floor_nbr)) as new_room_nbr3 from hotel4 )5 set room_nbr=new_room_nbr;
update (
select rowid as rid,room_nbr,(floor_nbr*100+row_number()over(partition by floor_nbr order by floor_nbr)) as new_room_nbr
from hotel
)
set room_nbr=new_room_nbrORA-01732: 此视图的数据操纵操作非法
这些方法都不可靠,当然,把UPDATE再嵌套一层也可以:
SQL> update hotel a2 set room_nbr =3 (select new_room_nbr4 from (select rowid as rid,5 room_nbr,6 (floor_nbr * 100 + row_number()7 over(partition by floor_nbr order by floor_nbr)) as new_room_nbr8 from hotel) bb9 where a.rowid = bb.rid);5 rows updatedSQL> select * from hotel;FLOOR_NBR ROOM_NBR
---------- ----------1 1011 1022 2012 2023 301SQL> rollback;Rollback completeSQL>
执行计划如下:
Plan Hash Value : 4147990906 -------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 5 | 30 | 28 | 00:00:01 |
| 1 | UPDATE | HOTEL | | | | |
| 2 | TABLE ACCESS FULL | HOTEL | 5 | 30 | 3 | 00:00:01 |
| * 3 | VIEW | | 5 | 125 | 4 | 00:00:01 |
| 4 | WINDOW SORT | | 5 | 30 | 4 | 00:00:01 |
| 5 | TABLE ACCESS FULL | HOTEL | 5 | 30 | 3 | 00:00:01 |
-------------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 3 - filter("BB"."RID"=:B1)
这种方法虽然能成功,但由执行计划可以看到,子查询执行了5次,对HOTEL有5次全表扫描。那么如果表更大,是不是更慢?博主之前就经常遇到有同事写出类似update SQL,上线的时候可能跑一晚上也跑不出来。
另一个方法是用MERGE语句:
SQL> merge into hotel a2 using (select rowid as rid,3 room_nbr,4 (floor_nbr * 100 + row_number()5 over(partition by floor_nbr order by floor_nbr)) as new_room_nbr6 from hotel) bb7 on (a.rowid = bb.rid)8 when matched then update set a.room_nbr = bb.new_room_nbr;5 rows mergedSQL> select * from hotel;FLOOR_NBR ROOM_NBR
---------- ----------1 1011 1022 2012 2023 301SQL>
执行计划如下:
Plan Hash Value : 1282884214 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
---------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 5 | 80 | 7 | 00:00:01 |
| 1 | MERGE | HOTEL | | | | |
| 2 | VIEW | | | | | |
| * 3 | HASH JOIN | | 5 | 220 | 7 | 00:00:01 |
| 4 | VIEW | | 5 | 190 | 4 | 00:00:01 |
| 5 | WINDOW SORT | | 5 | 30 | 4 | 00:00:01 |
| 6 | TABLE ACCESS FULL | HOTEL | 5 | 30 | 3 | 00:00:01 |
| 7 | TABLE ACCESS FULL | HOTEL | 5 | 30 | 3 | 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("A".ROWID="BB"."RID")
通过PLAN可以看到,使用MERGE子查询只对hotel访问了一次,效率提高了很多。
三、隔行抽样
有时为了取样而不是查看所有的数据,要对数据进行抽样,前面介绍过选取随机行,这里将介绍隔行返回。
现在有下面需求:对员工表中的数据每隔一行返回一个员工。
为了实现这个目标,用求余函数mod即可,我们看一下mod的结果。
SQL> select *2 from (select mod(rn, 2) as md, aa.*3 from (select rownum as rn, a.*4 from (select ename, empno, sal from emp order by ename) a) aa)5 where md = 0;MD RN ENAME EMPNO SAL
---------- ---------- ---------- ----- ---------0 2 ALLEN 7499 1600.000 4 CLARK 7782 2450.000 6 JAMES 7900 950.000 8 KING 7839 5000.000 10 MILLER 7934 1300.000 12 SMITH 7369 800.000 14 WARD 7521 1250.007 rows selected
通过这个函数,想间隔几行返回都可以实现。
总结
本篇博客主要给大家介绍了:
- 分析查询的一个小建议,可能大家平时为了方便,用row_number做分页的比较多,但是在有些场景,这个效率真的挺低。
- 我身边很多人都会认为分析函数比传统写法简单并且效率高,无论什么场景都一股脑用分析函数,但是很多时候都会出现效率低下的问题,究其原因类似第二种案例,也建议大家在实际开发过程中,注意下。
- 最后介绍的这个隔行抽样是某网友问我的一个某国企的面试题,也放上来啦。
相关文章:
【SQL开发实战技巧】系列(二十二):数仓报表场景(上) 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…...

小米无线AR眼镜探索版细节汇总
在MWC 2023期间,小米正式发布了一款无线AR眼镜,虽然还没看过实机,但XDA提前上手体验,我们从中进行总结。首先我要说的是,小米这款眼镜和高通无线AR眼镜参考设计高度重叠,产品卖点几乎一致,只是增…...

Web3中文|Litra:简洁而优美的NFT流动性协议,能给NFT市场带来什么?
2021年,NFT元年2021年,无疑是 NFT 的“元年”。这一年推特创始人的首条推特被拍出250万美元,加密艺术家Beeple的数字作品“First 5000 Days”在佳士得以6900万美元价格成交,无聊猿最高上涨了1800倍。2021年11月,在Goog…...

SSL证书对虚拟主机的用处有哪些?
虚拟主机是指在同一台服务器上,通过不同的域名或IP地址为多个网站提供服务的一种网络主机。而SSL证书则是一种数字证书,它用于加密网站与用户之间的通信,确保数据传输的安全性和完整性。在虚拟主机上,SSL证书有以下几个用处&#…...

SpringCloud之MQ笔记分享
MQ异步通信 初始MQ 同步通信 优点:时效性较强,可以以及得到结果 Feign就属于同步方式–问题: 耦合问题性能下降(中间的等待时间)资源浪费级联失败 异步通信 优点 耦合度低性能提升,吞吐量高故障隔离…...

动态规划背包问题
背包问题的分类 拿到背包问题,最重要的是会归类到哪一种背包问题中,常见的考题里主要是01背包和完全背包,leetcode上连多重背包的题目都没有。实际完全背包问题就是01背包的一种。 对一和零这道题,很多人容易把m看成一个背包,n看成另一个背包,从而当做多重背包。然而这…...
OpenCV4.x图像处理实例-张嘴和闭嘴检测
张嘴和闭嘴检测 在活体验证中,张嘴和闭嘴检测也是一个重要的环节。本文将介绍如何通过检测人脸上唇和下唇的关键点,并计算上唇和下唇的关键点的距离来检测当前人脸状态是否处于张嘴或闭嘴。 张嘴和闭嘴检测主要步骤如下: 第一步,安装依赖库 示例中使用到OpenCV和MediaP…...
软考高级系统分析师系列论文之十二:论实时控制系统与企业信息系统集成在工业控制的常规应用
软考高级系统分析师系列论文之十二:论实时控制系统与企业信息系统集成在工业控制的常规应用 一、摘要二、正文三、总结一、摘要 本文通过“工控组态软件”项目的开发,着重讨论实时系统与信息系统的集成。近年来,国内外的组态软件取得了很大的发展,已广泛应用于企业生产。组…...
蓝桥杯入门即劝退(二十三)货物摆放问题
欢迎关注点赞评论,共同学习,共同进步! ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法,欢迎订阅专栏共同学习交流! 你的点赞、关注、评论、是我创作的动力! -------希望我的文章…...

经验之谈——指标异常了怎么办?
本文参考了数据万花筒的文章,结合我自己工作经验。希望给大家一些帮助。 指标异常排查,是数据分析师的工作重点之一,是各行各业数据分析师都绕不开的话题。 本文试图回答: 1、指标波动的影响因素有哪些? 2、如何快速…...
影视领域解说电影怎样做才会更加出彩?
还有没有想要做影视解说的新手朋友~给大家分享一下影视解说快速上手的软件工具! 一、解说文案 文案是影视解说中最重要的步骤,如果你无法保证文案足够优秀,那么请务必让所有语句通顺,整体通篇下来让人知道你是在讲一个完整的故事…...

【Spring6】| Spring对IoC的实现(核心重点)
目录 一:Spring对IoC的实现 1. IoC 控制反转 2. 依赖注入 2.1 set注入 2.2 构造注入 3. set注入专题 3.1 注入外部Bean 3.2 注入内部Bean 3.3 注入简单类型 3.4 级联属性赋值(了解) 3.5 注入数组 3.6 注入List集合和Set集合 3.7…...

部门来了个测试工程师,听说是00后,实在是太卷了.....
都说00后躺平了,但是有一说一,该卷的还是卷。 这不,前段时间我们部门来了个00后,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。…...

冲冲冲,力扣javascript刷题——数组总结
力扣javascript刷题——数组总结冲冲冲,力扣刷题——数组总结1.二分查找力扣704题:二分查找35.搜索插入位置34.在排序数组中查找元素的第一个和最后一个位置69.x 的平方根367. 有效的完全平方数2.双指针法27. 移除元素26. 删除有序数组中的重复项283.移动零844. 比较…...

使用kotlin编写html dsl框架
前排提醒,这个框架就是我写着玩的,如果您已经会使用vue或其他前端框架,这篇文章可能对您没有什么意义。即使您不会如上提到的框架,也不要对该框架报有过高的期待,该框架更多的是,我自己的自娱自乐。 这里还…...

【谷粒学院】MybatisPlus(1~17)
1.项目介绍 2.项目背景介绍 3.项目商业模式介绍 4.项目功能模块介绍 5.项目技术点介绍 6.项目技术点-MybatisPlus介绍 官网:http://mp.baomidou.com/ MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做…...
C++的输入输出
目录 一、基本的输入输出 二、I/O库头文件 三、标准输出流(cout) 四、标准输入流(cin) 五、标准错误流(cerr) 六、标准日志流(clog) 一、基本的输入输出 C 标准库提供了一组丰…...

RNN相关知识总结
目录RNN结构与原理1.模型总览2.反向传播LSTM结构与原理1.模型总览2.如何解决RNN梯度消失/爆炸问题?GRU结构及原理1.模型总览LSTM与GRU的区别RNN结构与原理 1.模型总览 上图是RNN的展开结构图,由输入层、隐藏层和输出层组成。当前时间步t 的隐藏状态hth_…...
2. 应用C/C++编写程序
2.1 一个完整的C++源程序 例题是参考书《C++程序设计--基础,编程抽象与算法策略》第一章的PowersOfTwo.cpp。当运行程序PowersOfTow时,计算机要询问指数是多少,即2的多少次方。例如,输入8,程序会产生2的0到8次方的值。 /* File: PowersOfTwo.cpp *程序注释 …...

Spring Boot 统一功能处理(用户登录权限效验-拦截器、异常处理、数据格式返回)
文章目录1. 统一用户登录权限效验1.1 最初用户登录权限效验1.2 Spring AOP 统一用户登录验证1.3 Spring 拦截器1.4 练习:登录拦截器1.5 拦截器实现原理1.6 统一访问前缀添加2. 统一异常处理3. 统一数据格式返回3.1 统一数据格式返回的实现3.2 ControllerAdvice 源码…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
raid存储技术
1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...

【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境
如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境? 在 Python 开发中,为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具,能高效创建不同 Python 版本的 Poetry 虚拟环境,接下来…...