SQL中order by的高级用法
一、ORDER BY返回的是游标而不是集合
SQL的理论其实是集合论,常见的类似求数据的交集、并集、差集都可以使用集合的思维来求解。
集合中的行之间没有预先定义的顺序,它只是成员的一种逻辑组合,成员之间的顺序无关紧要。
如下图,每一个括号里的内容就是一条记录,在没排序前,他们都是随机分布在集合中。
Student集合
如下图,经过对Student表的ID进行ORDER BY排序后,Student表变成了有序对象,也就是我们上面说的游标。
Student(ID,Name,Age)
Student对象
这里涉及SQL语句的语法顺序和执行顺序了,我们常见的SQL语法顺序如下:
SELECT DISTINCT <Top Num> <select list>而数据库引擎在执行SQL语句并不是从SELECT开始执行,而是从FROM开始,具体执行顺序如下(关键字前面的数字代表SQL执行的顺序步骤):
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>
(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>
示例表Customers结构及数据如下:
1、WHERE后面不使用别名的情况
SELECT 姓名 AS Name, 地址 AS Address, 城市 AS City FROM Customers WHERE 城市='广州'结果如下:
SELECT 姓名 AS Name, 地址 AS Address, 城市 AS City FROM Customers WHERE City='广州'
从返回的消息中我们可以看到,重命名后的City并不能被WHERE识别,所以才会报“列名'City'无效”的提示。
SELECT 城市 AS City FROM Customers GROUP BY City
结果如下:
4、测试HAVING后使用列别名
SELECT 城市 AS City FROM Customers GROUP BY 城市 HAVING COUNT(City)>1
结果如下:
5、测试ORDER BY后面使用列别名
SELECT 姓名 AS Name, 地址 AS Address, 城市 AS City FROM Customers ORDER BY City
结果如下:
有些小伙伴为了图省事,喜欢在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
得到的结果并不是我们想要的,所以请慎用ORDER BY加数字,尽量使用ORDER BY加列名或列别名。
CREATE VIEW V_Customers AS SELECT 客户ID AS ID, 姓名 AS Name, 地址 AS Address, 城市 AS City FROM Customers ORDER BY ID,Name,Address结果如下:
这里我猜测是因为视图,内联表值函数,派生表(子查询)和公用表表达式(CTE)等返回的结果还需要进一步的去使用,加了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
结果如下:
SELECT TOP 3 * FROM Customers ORDER BY 城市结果如下:
而不保证结果集的排列顺序,因为表表达式外面至少还有一层才是我们最终需要的结果集。
这里的ORDER BY只对当前的子查询生效,到了主查询是不起作用的。必须在主查询末尾继续添加一个ORDER BY子句才能对结果集生效,就像我们例子中写的那样。
除非逻辑要求,一般情况下并不推荐大家这样巧妙的避开子查询中不能使用ORDER BY的限制。
个人公众号:SQL数据库开发
#搞技术你要知道#