SQL中order by的高级用法

您所在的位置:网站首页 orderby可以接聚合函数吗 SQL中order by的高级用法

SQL中order by的高级用法

2024-07-15 23:12| 来源: 网络整理| 查看: 265

导读

为什么只有ORDER  BY后面可以使用列别名

为什么不推荐使用ORDER BY后接数字来排序

为什么视图和子查询里面不能使用ORDER BY

    ……

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

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

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

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

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

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

Student(ID,Name,Age)

cb43d0d837a32761ca708177bafb9388.png

Student集合

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

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

Student(ID,Name,Age)

37e6184ec4b58d38cebd90dbec29a5b1.png

Student对象

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

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

SELECT DISTINCT   FROM [left_table] JOIN ON WHERE GROUP BY WITH HAVING ORDER BY  

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

(8)SELECT (9)DISTINCT  (11) (1)FROM [left_table](3) JOIN (2)        ON (4)WHERE (5)GROUP BY (6)WITH (7)HAVING (10)ORDER BY  

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

我们举例测试一下。

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

5515fad313d79e0b7d9f0a09122e2507.png

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

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

结果如下:

28ed9eef44c81a24c811181cc6876e53.png

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

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

执行结果如下:

b739b840639942e1bd9d9d8b0df201e7.png

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

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

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

SELECT  城市 AS City FROM Customers GROUP BY City

结果如下:

5f8ed69d5d3406ccb0425689bf961022.png

4、测试HAVING后使用列别名

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

结果如下:

8ec46fb1db370e503bab11ce59efa456.png

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

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

结果如下:

a31304f33fd43f245e3cbebe893617d6.png

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

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

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

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

结果如下:

266a8d7f3f3759f5acc604f78604483c.png

这样写的结果,针对当前的查询是正确没有问题的,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加数字,排序后的结果如下:

9e31a632ae3351ecf399886785840108.png

得到的结果并不是我们想要的,所以请慎用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

结果如下:

ce8120cdde59a96518cc7337634e643b.png

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

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

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

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

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

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

9ee0cd579275216be7f791c2458454f7.png

这又是为什么呢?

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

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

结果如下:

5ca0d940e1ef0a09695f02665e26ae4d.png

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

SELECT TOP 3 * FROM Customers ORDER BY 城市

结果如下:

15b8208c657c4cd4fb34326a0e1e6d7f.png

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

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

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

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

觉得不错,记得转发分享给更多人,谢谢啦~

f0200602a55caf2a82d2f4d38d45a084.gif

我是岳哥,最后给大家分享我写的SQL两件套:《SQL基础知识第二版》和《SQL高级知识第二版》的PDF电子版。里面有各个语法的解释、大量的实例讲解和批注等等,非常通俗易懂,方便大家跟着一起来实操。

有需要的读者可以下载学习,在下面的公众号「数据前线」(非本号)后台回复关键字:SQL,就行

数据前线

61a9ad62a3141ff9ceeff03781188bbb.png

——End——

后台回复关键字:1024,获取一份精心整理的技术干货

后台回复关键字:进群,带你进入高手如云的交流群。

推荐阅读

互联网公司常用 MySQL 分库分表方案

一条SQL能占多大内存?

SQL中的递归查询

SQL高效查询建议

MySQL中,21个写SQL的好习惯2af02973a1c9ce1a35837111bf25fea2.gif



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3