【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 源码…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...