Oracle 查询技巧与优化(一) 单表查询与排序
前言
作为一个程序员在写SQL时往往注重结果而忽略了本该应用的技巧和更优性能的选择(之前本人一直也是这样),当公司没有一个DBA(据我了解大多数中小公司都是没有的)为我们做SQL优化时那我们理应将SQL尽可能的写的高效简洁,而不是拿“我是一个java程序员或.NET程序员不擅长这些”为借口,博主本人也是以能写出更高效和更优秀的SQL为目标而构想出本系列blog,通过实际的生产环境数据进行演练并总结学习一些程序员也应当具备的某些DBA的素质,废话不多说,首先开始第一篇学习与总结,第一篇相对比较简单,回顾一下oracle中基本的查询操作和一些函数。
单表查询与排序
首先准备数据,这里的数据是从生产环境DB中备份出来的,即某市考试招生系统的一个基础学生信息表,数据量也不大大概1W+,约50个字段,主要是学生的个人基本信息:
接下来看一下几个较为简单的查询技巧和注意点。
分页排序
如题,从分页语句开始,都知道oracle中是通过rownum来进行分页的,例如我们查询20条到30条之间的数据:
select *from (select rownum rn, t.*from (select sid_, stuname_, csrq_ from t_studentinfo) twhere rownum <= 30) swhere s.rn > 20
如上所示,这种分页方式在绝大多数情况下是最高效的,而并非是通过s.rn>20 and s<=30,因为这种不如上面的效率高。接下来如果在分页的基础上添加排序,例如:查询20条到30条之间的数据并按出生日期(csrq_)排序,很简单,我们只需在最里层的查询中加上排序语句即可:
select *from (select rownum rn, t.*from (select sid_, stuname_, csrq_from t_studentinfoorder by csrq_) twhere rownum <= 30) swhere s.rn > 20
查询结果如下图所示:
取随机n条记录排序
如题,很简单,利用oracle提供的随机函数包dbms_random来完成,首选简单了解一下随机数,即dbms_ramdom.value:
select dbms_random.value from dual
运行上述SQL即可以返回一个大于0小于1的38位精度的随机数,如下图:
搞清楚了这一点,我们接下来就写一个按随机数排序,例如取学生表的前10条数据并按随机数排序,比如这样写:
select bmh_, stuname_, csrq_from T_STUDENTINFOwhere rownum < 10order by dbms_random.value;
连续运行三次,看一下查询结果:
乍一看仿佛没问题,没错,是按随机数排序了,每次运行结果的顺序都不一样,但是请仔细观察,这三次运行结果的学生仿佛是同一批人,只是顺序发生了改变,没错,这才是问题的关键,我们上面的写法是先取学生,后排序,也就是说结果已经提前确定,只是顺序在发生变化,这样的效果并不是我们预期的,我们期望的是在全体学生中随机抽取10人,所以我们需要改写一下我们的SQL,使其先让全体学生排序,再取前10名学生:
select t.*from (select bmh_, stuname_, csrq_from T_STUDENTINFOorder by dbms_random.value) twhere rownum < 10
这回再连续运行三次看一下查询结果:
这次再仔细观察一下三次的运行结果很明显已经没有一个重复的人了,这也就达到了我们的预期,所以往往SQL的书写顺序也对结果有着决定性的影响,这一点尤为重要。
查询中的条件逻辑
如题,oracle提供了case…when语句使得我们可以在SQL中灵活运用多条件分支来根据值转换为不同的查询结果,例如:
select sid_,stuname_,case mzdm_when 1 then'汉族'when 3 then'满族'when 4 then'回族'when 9 then'蒙古族'end as mzfrom t_studentinfowhere sid_ in ('36697', '34115', '39590', '30692')order by mzdm_
查询结果如下:
在实际应用中像这种民族code肯定应该关联对应的字典表的键来获取值,这里我们仅仅想演示一下case…when语句的用法,显而易见,以case开头并以end结尾,中间是when条件,并在end关键字之后可以通过as起别名,很方便。
空值转换
如题,又是一个很常用的东西,比如如果某一列查询为空时,我们想将空值替换为我们指定的一个值,这里就可以选择nvl函数或者coalesce函数,均可以达到期望的效果:
select tcsdm_ from t_studentinfo where sid_ in ('33405','29982','28974');
select nvl(tcsdm_,'999') tcsdm from t_studentinfo where sid_ in ('33405','29982','28974');
select coalesce(tcsdm_,'999') tcsdm from t_studentinfo where sid_ in ('33405','29982','28974');
运行结果如下图:
但这里还是要区分一下这两个函数的用法,首先nvl函数只能传2个参数:NVL( string1, replace_with)
,功能很简单,即:如果string1为NULL,则NVL函数返回replace_with的值,否则返回原来的值。再需要注意一点就是string1与replace_with需要保持同一数据类型,接下来再看一看coalesce函数,它是支持多个参数的,形如:COALESCE(exp1,exp2,...,expn),n>=2
,同样它的含义也和nvl区别很大(尽管它们达到的效果相同),即:返回第一个不为空的表达式,如果都为空则返回空值。关于使用哪一个好应该也是显而易见的,即在多参数的情况下coalesce函数明显更具优势,因为它避免了需要嵌套nvl函数,若是只有两个参数的话就无所谓了,正如我们上面的例子,看个人喜好。
模糊查询中的通配符
如题,偶尔在查询中也会遇到这种问题,首先创建一个测试用的视图:
create or replace view v_test_02 asselect '_AAA' as column1 from dualunion allselect '_\AAA' as column1 from dualunion allselect '_AAAB_' as column1 from dualunion allselect 'QAAA' as column1 from dual;
直入主题,需求是我想查询包含字符串“_AAA”的结果,那么条件中的like语句该怎么写呢?我们先试一下这样写看看:
select * from v_test_02 where column1 like '_AAA%';
看一下运行结果:
如上图所示,第三行的QAAA这个结果并不是我们预期希望得到的,但是通配符“_”就代表1个字符,所以这个Q自然会被该通配符匹配到,无可厚非,所以为了解决这个问题我们必须引入转义字符的概念,下面是修改后的SQL:
select * from v_test_02 where column1 like '\_AAA%' escape '\';
此时再看一下查询结果:
这次就对了,所以此处注意一下转义字符以及escape关键字的用法,尽管这种情况很少遇见,但也值得一提。
多字段排序
很有意思的一个问题,这里我们拿学生成绩表的数据来举例更贴切一些,学生成绩表也很简单,包含了学生的考号、各科的文化课成绩以及总分,这里我们只查3列,假设我们的排序条件是这样的:按总分倒序排列并按语文的单科成绩升序排列,那得到的结果会是怎么的呢?首先看一下SQL语句:
select sid_, totalscore_, ywscore_from T_STUDENTSCORE torder by 2 desc, 3 asc
再看一下运行结果:
如上图所示,首先有一个小地方就是order by后面写的数字,2就代表第2列,3就代表第3列,当然也可以直接跟列名,观察一下查询结果,不难发现依旧是按totalscore_(总分)倒序排列的,但ywscore_(语文单科成绩)似乎排列的有有些混乱,没关系,注意一下图中我用红色格子隔开的列,一个格子一个格子看,不难发现在每个格子内,它确实是升序排列的,这就是多字段排序的结论,即:以写在靠前位置的排序列为基准,将靠后位置的排序列分成若干组,然后每组的数据再单独进行排序。
空值排序
如题,如果按某一列排序,但那一列存在许多空值,它们是如何显示的?在Oracle中空值默认排序在后面,比如学生表中有许多学生没有填出生日期,我们又按出生日期这一列倒序排列,那么可以看到如下结果:
如上图所示,前112名学生的出生日期均为空,从113位学生开始,即年龄最小的学生依次排下去。那么也许你觉得这样并不好,明明为空为什么按大的算呢?我想把空的都放到前面去,很简单,只需要在SQL末尾加上两个关键字(nulls last)即可:
这回可以看到前面并没有空值了,出生日期大的排在最前面,而空的已经排在了11000+的末尾位置了。
总结
简单记录了一下在单表查询与排序中我个人认为值得关注和常用一些点(如果还有好的优化方式或者应当关注的点后面还会陆续添加,也欢迎各位提出毕竟我个人能力有限),部分知识点和灵感来自《Oracle查询优化改写》书中,但我是以程序员的视角而非DBA(也达不到)去描述在项目中遇到的或可能遇到的种种查询语句,并结合实际生产环境的数据进行举例说明,旨在提高我作为程序员应当具备和提高的SQL能力,当然如果有同学能从本系列blog中得到提升那就更好了,希望如此,The End。
Oracle 查询技巧与优化(一) 单表查询与排序相关推荐
- mysql 连表查询 好处,MySQL 多次单表查询和多表联合查询的优缺点分析-Fun言
前言 阿里巴巴的代码规范中有一条就是不建议执行三张表以上的多表联合查询,因为对数据量不大的应用来说, 多表联合查询开发高效, 但是多表联合查询在表数据量大, 并且没有索引的时候, 如果进行笛卡儿积, ...
- 记录一次慢SQL优化:大表关联小表->拆解为单表查询
前言: 最近一段时间总是会收到数据库CPU报警 一查发现有一个特别慢的SQL,调用的频率很高,并且查一次SQL15s以上,十分影响性能 SQL分析 这个sql是一个分页查询的sql,每次查出10条主表 ...
- mysql单表查询与多表查询小练习
目录 一: (1).创建emp表 (2).插入数据 编辑-- 1. 查询出部门编号为30的所有员工 编辑-- 2. 所有销售员的姓名.编号和部门编号. -- 3. 找出奖金高于工资的员工. -- ...
- 单表查询和多表连接查询哪个效率更快?
这段时间在做项目的过程中,遇到一个模块,数据之间的联系很复杂,在建表的时候就很纠结,到底该怎么去处理这些复杂的数据呢,是单表查询,然后在业务层去处理数据间的关系,还是直接通过多表连接查询来处理数据关系 ...
- mysql 单表查询
单表查询 语法: 一.单表查询的语法SELECT 字段1,字段2... FROM 表名WHERE 条件GROUP BY fieldHAVING 筛选ORDER BY fieldLIMIT 限制条数 二 ...
- php单表查询语句,单表查询
一.SQL数据查询的一般格式 数据查询是数据库的核心操作.SQL提供了SELECT语句进行数据查询,其一般格式为: SELECT [ALL | DISTINCT][,]··· FROM[,···] | ...
- SQL数据查询之——单表查询
一.SQL数据查询的一般格式 数据查询是数据库的核心操作.SQL提供了SELECT语句进行数据查询,其一般格式为: SELECT [ALL | DISTINCT]<目标列表达式>[,< ...
- 数据库标准语言SQL(六)——单表查询(二)
数据库标准语言SQL(五)--查询(二) 一.前言 这一次内容继续是单表查询的部分,然后单表查询就结束了. 二.示例 1.用值表确定集合查询 引入谓词IN 查找属性值属于指定集合的元组,可以让我们在查 ...
- SQL Server 数据库之单表查询
单表查询 1. 概述 2. 单表查询命令 2. 无条件查询与条件查询 2.1 无条件查询 2.2 条件查询 3. 聚集函数 4. 分组查询 5. 排序查询 1. 概述 单表查询是只对一个数据表进行查询 ...
最新文章
- Android系统SVC命令教程
- php循环输出多个网络地址图片,php中curl循环往请求多个URL和多线程去请求多个URL的方法...
- linux 交叉编译 libxml2,openssl,libssh2
- Android SQLite (三 ) 全面详解(一)
- 运行命令对电脑的操作(Windows + R)
- data URI scheme及其应用
- 有趣的灵魂百里挑一,Linux同学你低下头干嘛,起来说下这个问题。
- 配置tomcat_Tomcat 配置必备的 10 个小技巧,让你轻松玩转Tomcat
- django 1.8 官方文档翻译:9-1-4 格式本地化
- python中class什么意思_【转载】在python的class中的,self到底是什么?
- java jbutton 不显示_java让JButton按钮变成不可见
- PowerPoint 蜜蜂跳“8”字舞实例
- Ubuntu14.04 用 CrossOver 安装 TMQQ2013
- 个人随手日志之astah professional
- QQ、微信、QQ浏览器UserAgent
- 「AI产品」产品小姐姐分析抖音背后的计算机视觉技术
- 医学影像-深度学习综述
- 普通话测试app怎么样可以不交钱_和小首一起好好说普通话!
- 服务器显示htx插槽,Socket F接口Opteron主板与服务器Computex展示
- Vue仿饿了么app项目总结
热门文章
- niginx参数配置详解(转)
- Spring - 装配bean
- Axure RP教程
- java snakeyaml_JAVA使用SnakeYAML解析与序列化YAML
- 彩灯控制器课程设计vhdl_基于VHDL的彩灯控制器设计与实现毕业设计(DOC毕业设计论文)...
- oracle查不到凭证,用友T3软件在查询凭证界面怎么查不到已经做的凭证了
- 个人信息保护建设面临的问题和困境及解决方案
- CRectTracker(橡皮筋)类的使用
- SharedPreferences中Json对象session部分字符串替换
- 【C++】Visual Studio教程(五) -安装 Visual Studio