Oracle查询优化改写技巧与案例 第二章 给查询结果排序

2.1以指定的次序返回查询结果
实际提取数据或生成报表时,一般都要根据一定的顺序查看,比如,想查看单位所雇员工的信息:
这种语句很多人都会写,但除了"ORDER BY hiredate ASC"这种写法,还可以写成"ORDER BY 3 ASC",意思是按第三列排序。
当取值不定时,用这种方法就很方便,比如,有时取sal,有时要取comm来显示:
对于这种需求,如果在order by 后使用列名,就需要注意前后保持一致,否则会给开发软件带来“小麻烦”。比如,开发初期的语句如下:
后来要求增加empno的显示,而我们经常要按第一列排序,于是需要改为:
如果语句比较复杂,会经常忘记更改后面的order by,但使用“order by 3”这种方式就没有问题。
需要注意的是,用数据来替代列位置只能用于order by 子句中,其它地方都不能用。
2.2按多个字段排序
如果按多列排序且有升有降怎么办?例如,按部门编号升序,并按工资降序排列。
排序时有两个关键字:ASC表示升序、DESC表示降序。
所以我们在order by后加两列,分别标明ASC、DESC。
下面用图的形式进行介绍,如下图所示,按多列排序时,若前面的列有重复值(如deptno=10有3行数据),后面的排序才有用。相当于是通过前面的列把数据分成了几组,每组的数据在按后面的列进行排序。

2.3按子串排序
有一种速查法就是按顾客电话号码尾号的顺序记录,这样在查找的时候就可以快速缩小查询范围,增强顾客的认可度。如果要按这种方法排序,应该怎样做呢?通过函数取出后面几位所需的信息即可。
按子串排序实际就是增加一个计算列,然后用这个计算列来排序。
2.4从表中随机返回n条记录
为了防止做假,像前面那样抽查数据还不行,还需要随机抽查。
我们可以先用dbms_random来对数据进行随机排序,然后取其中三行。
有人会问:为什么要嵌套一层呢?直接这样用多好。
你可以运行一下看,为了便于观察,我们对得到的结果进行排序,运行下面的语句就可以。
多运行几次,会发现每次得到的数据都一样,而不是随机的。
为了便于解释,我们先对上面的语句进行等价改写:
查询语句中这几处的执行顺序为:
SELECT
ROWNUM
ORDERBY
也就是说,要先取出数据,然后生成序号,最后才是排序。
我们可以通过子查询把排序前后的序号分别取出来对比。
同样,你可以多运行几次,看是不是与刚才描述的一致。
因此,正确的写法是:先随机排序,再去数据。
错误的写法是:先取数据,在随机排序
2.5TRANSLATE
语法格式:TRANSLATE(expr,from_string,to_string)
示例如下:
from_string 与to_string以字符为单位,对应字符一一替换。

如果to_string为空,则返回空值。
如果to_string对应的位置没有字符,则from_string中列出的字符将会被消掉。

2.6按数字和字母混合字符串中的字母排序
首先创建VIEW如下:
这个需求救难一点了,看到里面的字母(也就是原来的列ename)了吗?要求按其中的字母(列ename)排序。
那么就要先取出其中的字母才行,我们可以用translate的替换功能,把数字与空格都替换为空:
2.7处理排序空值
Oracle默认升序默认空值在后,降序空值在前。
如果想要更改空值顺序,则可以用关键字NULLS FIRST和NULL LAST。
2.8根据条件取不同列中的值来排序
有时排序的要求会比较复杂,比如,领导对工资在1000到2000元之间的员工更感兴趣,于是要求工资在这个范围的员工要排在前面,以便优先查看。
对于这种需求,我们可以在查询中新生成一列,用多列排序的方法处理:

可以看到,950与2850都排在了后面,也可以不显示级别,直接把case when放在order by中:
