导读

  • 为什么只有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用法,避坑相关推荐

  1. 【React Native】react-native-vector-icons用法避坑

    在用React Native开发App时,icon的使用必不可少.官网推荐使用react-native-vector-icons来完成icon的使用. 在学习的过程中碰到了一个问题:一步一步按照官网说 ...

  2. k8s+kubeedge+sedna安装全套流程+避坑指南+解决办法

    最近在学习边缘计算要用到kubeedge,安装了好多次总会遇到各种各样的问题,因此在这里一一列出,以方便下次安装.则里面可能出错的地方太多,如果有问题,请私信联系. 一.环境准备 节点 IP 环境 软 ...

  3. 17条避坑指南:一份来自谷歌的数据库经验贴

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://medium.com/@rak ...

  4. 避坑!使用 Kubernetes 最易犯的 10 个错误

    Kubernetes 作为大规模企业级应用容器编排的首推工具,其为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,本文作者 Marek Bartik 深入分享了 K8s 的避坑 ...

  5. Mac OSX 下高效安装 homebrew 及完美避坑姿势

    Mac OSX 下高效安装 homebrew 及完美避坑姿势 Homebrew 是什么 Homebrew是 mac的包管理器,仅需执行相应的命令,就能下载安装需要的软件包,可以省掉自己去下载.解压.拖 ...

  6. RPA for Python(tagui)避坑指南 - 以咸鱼之王为例

    文章目录 前言 init click 点击函数 snap 截图函数 read ocr函数 结语 前言 这两天测试使用了一下 RPA for Python (以下简称pytagui,本质上就是用的tag ...

  7. HarmonyOS实战 —基于hi3861芯片鸿蒙2.0的避坑指南

    HarmonyOS实战 -基于hi3861芯片鸿蒙2.0的避坑指南 特别说明:本文章与卡片开发无关,想看卡片开发的不用往下读了 最近学习鸿蒙设备开发的过程中遇到了很多问题,因为目前几乎所有设备开发教程 ...

  8. SpringBoot 中JPA集成PostgreSql(详细步骤)避坑!

    SpringBoot 中JPA集成PostgreSql(详细步骤) 什么是JPA?(Java Persistence API) Spring Data JPA, part of the larger ...

  9. 赛元单片机触摸按键调节及避坑指南(以SC92F8461B的高灵敏触摸为例)

    目录 前言 流程总览 步骤说明 1.烧录官方高灵敏hex文件 2.目标板连接电脑并选择初始参数 3.参数调整 4.验证相互间影响 5.将配置信添加到工程 6.灵活调整 总结 前言 项目中前前后后用到过 ...

最新文章

  1. HA: InfinityStones靶机渗透测试
  2. 图像配准----NCC
  3. PlentyOfFish.com .NET网站的又一传奇
  4. unity3d Aniso Level 摄像机近地面清楚,远地面模糊
  5. TCP半连接队列(syns queue)和全连接队列(accept queue)
  6. ASP/COM+组件开发辅助软件之补充
  7. 双蓝牙(HC-05、HC-06)AT指令配对教程
  8. Knockout.Js官网学习(event绑定、submit绑定)
  9. matlab 暴雨强度公式,利用MATLAB推导城市暴雨强度公式
  10. svn 回退/更新/取消至某个版本命令详解
  11. 人工智能时代都需要哪些数学知识?这些经典教材给你划重点
  12. 云南计算机专升本数据结构_云南专升本-数据结构历年试题及答案.doc
  13. 好儿优机器人_好儿优机器人app
  14. arduino并口屏_74HC595等串口转并口芯片的Arduino实用封装
  15. 怎么把动态ip改成静态ip?
  16. Spring AOP配置 之 @Aspect
  17. Windows 10无法打开设置
  18. 效果图网站、外包平台接单平台有哪些?
  19. 软件工程的10个知识领域
  20. XML Publisher 模板开发小技巧

热门文章

  1. 戴尔服务器提升性能,解析戴尔12G服务器的主要性能提升和改进
  2. 这个emoji表情可使iphone变砖
  3. python无法正常启动0xc000007b_应用程序无法正常启动(0xc000007b)。
  4. 3KAB,贴片五脚芯片规格书
  5. ffmpeg 按帧数截取视频
  6. JO Smart聚视频 TV端软件
  7. 9.22生日——随笔
  8. 植树节|晓一叶之理,种一树美好
  9. 冬色烂漫 纯情踏雪 论著名画家冯庆冰雪画作品
  10. 【上课课件整理复习】第六章 网页数据的采集(1)