导读

  • 为什么只有ORDER BY后面可以使用列别名
  • 为什么不推荐使用ORDER BY后接数字来排序
  • 为什么视图和子查询里面不能使用ORDER BY

……

​小伙伴们在进行SQL排序时,都能很自然的使用到ORDER BY。不管是默认ASC的升序,还是DESC降序,几乎都是信手拈来。

今天给大家分享一些你可能不知道的ORDER BY用法。

一、ORDER BY返回的是游标而不是集合

SQL的理论其实是集合论,常见的类似求数据的交集、并集、差集都可以使用集合的思维来求解。

集合中的行之间没有预先定义的顺序,它只是成员的一种逻辑组合,成员之间的顺序无关紧要。

如下图,每一个括号里的内容就是一条记录,在没排序前,他们都是随机分布在集合中。

Student(ID,Name,Age)

Student集合

但是对于带有排序作用的ORDER BY子句的查询,它返回的是一个对象,其中的行按特定的顺序组织在一起,我们把这种对象称为游标。

如下图,经过对Student表的ID进行ORDER BY排序后,Student表变成了有序对象,也就是我们上面说的游标。

Student(ID,Name,Age)

Student对象

二、ORDER BY子句是唯一能重用列别名的一步

这里涉及SQL语句的语法顺序和执行顺序了,我们常见的SQL语法顺序如下:

SELECT DISTINCT <Top Num> <select list>
FROM [left_table]
<join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY <group_by_list>
WITH <CUBE | RollUP>
HAVING <having_condition>
ORDER BY <order_by_list>

而数据库引擎在执行SQL语句并不是从SELECT开始执行,而是从FROM开始,具体执行顺序如下(关键字前面的数字代表SQL执行的顺序步骤):

(8)SELECT (9)DISTINCT (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2) ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>

从上面可以看到SELECT在HAVING后才开始执行,这个时候SELECT后面列的别名只对后续的步骤生效,而对SELECT前面的步骤是无效的。所以如果你在WHERE,GROUP BY,或HAVING后面使用列的别名均会报错。

我们举例测试一下。

示例表Customers结构及数据如下:

1、WHERE后面不使用别名的情况

SELECT
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
WHERE 城市='广州'

结果如下:

2、WHERE后面使用列别名的情况

SELECT
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
WHERE City='广州'

执行结果如下:

从返回的消息中我们可以看到,重命名后的City并不能被WHERE识别,所以才会报“列名'City'无效”的提示。

其他关键字大家也可以使用上述方法进行测试,下面我们测试GROUP BY和HAVING后面使用列别名的情况。

3、测试GROUP BY后使用列别名

SELECT
城市 AS City
FROM Customers
GROUP BY City

结果如下:

4、测试HAVING后使用列别名

SELECT
城市 AS City
FROM Customers
GROUP BY 城市
HAVING COUNT(City)>1

结果如下:

注意:本文是以标准SQL来测试的,MySQL的HAVING 能使用列别名,是因为对此做了扩展,必须开启ONLY_FULL_GROUP_BY才可以。

5、测试ORDER BY后面使用列别名

SELECT
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
ORDER BY City

结果如下:

从上面的几个测试示例的结果中,可以得出我们的结论是正确的:ORDER BY子句是唯一能重用列别名的一步。

三、谨慎使用ORDER BY 后面接数字的方式来进行排序

有些小伙伴为了图省事,喜欢在ORDER BY后面写数字,具体示例如下:

SELECT
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
ORDER BY 1,2,3

结果如下:

这样写的结果,针对当前的查询是正确没有问题的,ORDER BY后面的数字1,2,3分别代表SELECT后面的第1,第2,第3个字段(也就是Name,Address,City)。

可是当查询的列发生改变,忘了修改ORDER BY列表。特别是当查询语句很长时,要找到ORDER BY与SELECT列表中的哪个列相对应会非常困难。

例如

SELECT
客户ID AS ID,
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
ORDER BY 1,2,3

由于增加了一列“客户ID”,原本的题意还是对Name,Address,City排序,但是因为使用了ORDER BY加数字,排序后的结果如下:

得到的结果并不是我们想要的,所以请慎用ORDER BY加数字,尽量使用ORDER BY加列名或列别名。

四、表表达式不能使用ORDER BY排序

表表达式包括视图,内联表值函数,派生表(子查询)和公用表表达式(CTE)。例如下面的视图是无效的

CREATE VIEW V_Customers AS
SELECT
客户ID AS ID,
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM Customers
ORDER BY ID,Name,Address

结果如下:

这个错误是不是很熟悉?因为很多小伙伴经常喜欢在视图或子查询里面加ORDER BY,然后一执行就会报这个错。

根本原因不敢妄加断定,因为搜寻了很多文献资料也没给出一个具体的说法。

这里我猜测是因为视图,内联表值函数,派生表(子查询)和公用表表达式(CTE)等返回的结果还需要进一步的去使用,加了ORDER BY进行排序是多此一举,反而会浪费系统资源。所以数据库的开发者不希望大家使用这样不规范操作。

所以下次就不要在表表达式里添加ORDER BY了。

五、T-SQL中表表达式加了TOP可以使用ORDER BY

我们从第四点的报错信息中可以看到:在另外还指定了 TOP、OFFSET 或 FOR XML是可以使用ORDER BY的。

这又是为什么呢?

我们还是先举个栗子给大家看一下

SELECT
客户ID AS ID,
姓名 AS Name,
地址 AS Address,
城市 AS City
FROM
(SELECT TOP 3 *
FROM Customers
ORDER BY 城市) Customers
ORDER BY ID,Name,Address

结果如下:

因为T-SQL中带有ORDER BY的表表达式加了TOP后返回的是一个没有固定顺序的表。因此,在这种情况下,ORDER BY子句只是为TOP选项定义逻辑顺序,就是下面这个逻辑子句

SELECT TOP 3 *
FROM Customers
ORDER BY 城市

结果如下:

而不保证结果集的排列顺序,因为表表达式外面至少还有一层才是我们最终需要的结果集。

这里的ORDER BY只对当前的子查询生效,到了主查询是不起作用的。必须在主查询末尾继续添加一个ORDER BY子句才能对结果集生效,就像我们例子中写的那样。

除非逻辑要求,一般情况下并不推荐大家这样巧妙的避开子查询中不能使用ORDER BY的限制。

以上就是有关ORDER BY的一些用法,你学会了吗?有不明白或疑问的地方,欢迎在底下留言。

参考:https://zhuanlan.zhihu.com/p/96733409

Oracle-除了会排序,你对ORDER BY的用法可能一无所知!的更多相关文章

  1. 对于Oracle中分页排序查询语句执行效率的比较分析

    转自:http://bbs.csdn.net/topics/370033478 对于Oracle中分页排序查询语句执行效率的比较分析 作者:lzgame 在工作中我们经常遇到需要在Oracle中进行分 ...

  2. Oracle rownum 分页, 排序

    Oracle rownum 分页, 排序 什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条ro ...

  3. 各种数据库分页语句整理以及Oracle数据库中的ROWNUM和ORDER BY的区别

    .oracle数据库分页 select * from (select a.*,rownum rc from 表名 where rownum<=endrow) a where a.rc>=s ...

  4. [大牛翻译系列]Hadoop(6)MapReduce 排序:总排序(Total order sorting)

    4.2.2 总排序(Total order sorting) 有的时候需要将作业的的所有输出进行总排序,使各个输出之间的结果是有序的.有以下实例: 如果要得到某个网站中最受欢迎的网址(URL),就需要 ...

  5. In Oracle 11g, how to change the order of the results of a sql without “order by”?(转)

    oracle 11g 当sql语句中不加order by的时候,好像是按rowid的顺序返回结果的.我也看过一些相关的文档,oracle的官方意思就是不加order by,就不保证输出的顺序. 那么, ...

  6. Mysql高手系列 - 第8篇:详解排序和分页(order by & limit),及存在的坑

    这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...

  7. ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法,先分组,然后在组内排名,分组计算,主表与附表一对多取唯一等

    ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法 今天在使用多字段去重时,由于某些字段有多种可能性,只需根据部分字段进行去重,在网上看到了row ...

  8. 转转转---ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法

    ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法   http://blog.csdn.net/yinshan33/article/detail ...

  9. SQL order by的用法

    首先,order by是用来写在where之后,给多个字段来排序的一个DQL查询语句. 其次,order by写法: 1.  select 字段列表/* from 表名 where 条件 order ...

随机推荐

  1. 零基础入门非常好的C语言基础资料

    C语言程序的结构认识 用一个简单的c程序例子,介绍c语言的基本构成.格式.以及良好的书写风格,使小伙伴对c语言有个初步认识. 例1:计算两个整数之和的c程序: #include main() { in ...

  2. hdu 3635 Dragon Balls(并查集)

    题意: N个城市,每个城市有一个龙珠. 两个操作: 1.T A B:A城市的所有龙珠转移到B城市. 2.Q A:输出第A颗龙珠所在的城市,这个城市里所有的龙珠个数,第A颗龙珠总共到目前为止被转移了多少 ...

  3. js 在浏览器中的event loop事件队列

    目录 前言 认识一个栈两个队列 执行过程 异步任务怎么分配 简单例子 难一点的例子 前言 以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意. 都说js是单线程的,不过它本身其 ...

  4. 开发笔记-----Ajax 基础使用

    一.GET 方式的用法: 1 <!--html --> 2 <div class="layui-form"> 3 <div class="l ...

  5. Docker多机网络

    前言 前面的文章主要聚焦于单机网络上,对于生产环境而言,单机环境不满足高可用的特点,所以是不具备上生产的条件,因此在开始Docker Swarm篇的时候我们先来聊聊多机网络之间Docker的通信如何做 ...

  6. 大一C语言学习笔记(6)---自省篇--流程控制;break,continue,return间的异同;数组应用到循环语句中需要注意的问题;++i 和 i++的异同等。

    下面是傻瓜博主"曾经"犯过的错和一些心得:        ༼ つ ◕_◕ ༽つ 1.要想流程控制学好,一定要学会化繁为简,举栗子: 三目运算符 (略?略:略)---就是一个数字嘛, ...

  7. 如何系统学习C 语言(下)之 预处理命令篇

    大话c语言(下)之 预处理命令篇 预处理就是在编译之前,通过一些预处理命令对源代码进行管理和控制的过程. 由源代码得到可执行的程序,会经过预处理.编译.汇编和链接几个过程 预处理命令大致可以分为文件包 ...

  8. Java学习(十五)

    下棋又被暴打 所以心态有点爆炸,学完习又去打云顶,忘记写博客了... 所以今天也有点水了,这下棋真是搞崩我心态了. Java学了函数重载 大概的要点在这 还有Web的学习,否定伪类. 如 p:not( ...

  9. 问题 B: 比大小

    题目描述 给你两个很大的数,你能不能判断出他们两个数的大小呢? 比如123456789123456789要大于-123456 输入 每组测试数据占一行,输入两个不超过1000位的10进制整数a,b 数 ...

  10. opa gatekeeper笔记:AdmissionReview input.request请求对象结构

    官方:https://v1-17.docs.kubernetes.io/zh/docs/reference/access-authn-authz/extensible-admission-contro ...