ORDER BY用法,避坑
导读
- 为什么只有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用法,避坑相关推荐
- 【React Native】react-native-vector-icons用法避坑
在用React Native开发App时,icon的使用必不可少.官网推荐使用react-native-vector-icons来完成icon的使用. 在学习的过程中碰到了一个问题:一步一步按照官网说 ...
- k8s+kubeedge+sedna安装全套流程+避坑指南+解决办法
最近在学习边缘计算要用到kubeedge,安装了好多次总会遇到各种各样的问题,因此在这里一一列出,以方便下次安装.则里面可能出错的地方太多,如果有问题,请私信联系. 一.环境准备 节点 IP 环境 软 ...
- 17条避坑指南:一份来自谷歌的数据库经验贴
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://medium.com/@rak ...
- 避坑!使用 Kubernetes 最易犯的 10 个错误
Kubernetes 作为大规模企业级应用容器编排的首推工具,其为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,本文作者 Marek Bartik 深入分享了 K8s 的避坑 ...
- Mac OSX 下高效安装 homebrew 及完美避坑姿势
Mac OSX 下高效安装 homebrew 及完美避坑姿势 Homebrew 是什么 Homebrew是 mac的包管理器,仅需执行相应的命令,就能下载安装需要的软件包,可以省掉自己去下载.解压.拖 ...
- RPA for Python(tagui)避坑指南 - 以咸鱼之王为例
文章目录 前言 init click 点击函数 snap 截图函数 read ocr函数 结语 前言 这两天测试使用了一下 RPA for Python (以下简称pytagui,本质上就是用的tag ...
- HarmonyOS实战 —基于hi3861芯片鸿蒙2.0的避坑指南
HarmonyOS实战 -基于hi3861芯片鸿蒙2.0的避坑指南 特别说明:本文章与卡片开发无关,想看卡片开发的不用往下读了 最近学习鸿蒙设备开发的过程中遇到了很多问题,因为目前几乎所有设备开发教程 ...
- SpringBoot 中JPA集成PostgreSql(详细步骤)避坑!
SpringBoot 中JPA集成PostgreSql(详细步骤) 什么是JPA?(Java Persistence API) Spring Data JPA, part of the larger ...
- 赛元单片机触摸按键调节及避坑指南(以SC92F8461B的高灵敏触摸为例)
目录 前言 流程总览 步骤说明 1.烧录官方高灵敏hex文件 2.目标板连接电脑并选择初始参数 3.参数调整 4.验证相互间影响 5.将配置信添加到工程 6.灵活调整 总结 前言 项目中前前后后用到过 ...
最新文章
- HA: InfinityStones靶机渗透测试
- 图像配准----NCC
- PlentyOfFish.com .NET网站的又一传奇
- unity3d Aniso Level 摄像机近地面清楚,远地面模糊
- TCP半连接队列(syns queue)和全连接队列(accept queue)
- ASP/COM+组件开发辅助软件之补充
- 双蓝牙(HC-05、HC-06)AT指令配对教程
- Knockout.Js官网学习(event绑定、submit绑定)
- matlab 暴雨强度公式,利用MATLAB推导城市暴雨强度公式
- svn 回退/更新/取消至某个版本命令详解
- 人工智能时代都需要哪些数学知识?这些经典教材给你划重点
- 云南计算机专升本数据结构_云南专升本-数据结构历年试题及答案.doc
- 好儿优机器人_好儿优机器人app
- arduino并口屏_74HC595等串口转并口芯片的Arduino实用封装
- 怎么把动态ip改成静态ip?
- Spring AOP配置 之 @Aspect
- Windows 10无法打开设置
- 效果图网站、外包平台接单平台有哪些?
- 软件工程的10个知识领域
- XML Publisher 模板开发小技巧