排序与语句执行顺序
对查询的结果进行排序
ORDER子句
SELECT 列名1,列名2…… FROM 表名 ORDER BY 列名n
默认升序(asc)
查询教师的姓名和职称 职称按拼音先后顺序排序
SELECT 姓名,职称 FROM 教师 ORDER BY 职称
SELECT 姓名,职称 FROM 教师 ORDER BY 职称 asc
自定义排序
跟Excel里差不多 给出自己想要的顺序就行了
查询教师的姓名和职称 职称按职称高低顺序排序 CASE……END WHEN……THEN
SELECT 姓名,职称 FROM 教师 ORDER BY
CASE WHEN 职称='教授' THEN 1
WHEN 职称='副教授' THEN 2
WHEN 职称='讲师' THEN 3
WHEN 职称='助教' THEN 4
ELSE 5
END
降序(desc)
排序选课成绩 从高到低 DESC
SELECT 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
可见在ORDER BY 中 就没有跟GROUP BY那样的要求对应显示
升降混合
对多个字段排序 查询员工名字和工资 按工资升序排 如果工作一样 再按名字降序排
Select ename,sal from emp order by sal asc,ename desc
sal在前 起主导 只有sal相等的时候才会考虑启用ename排序
按字段位置排序
Select ename,sal from emp order by 2 //2表示第2列
不健壮(列的顺序很容易发生改变) 不建议使用
TOP子句
SELECT TOP(N)【 PERCENT】列名(,列名……) FROM 表名
top(n) 前n个
top(n)percent 前百分之n
WITH TIES
前N个
找出前五名
SELECT TOP(5) 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
--还有很多相同成绩的 应该也入围 WITH TIES
SELECT TOP(5) WITH TIES 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
前百分之N
--PERCENT 百分比
--查询前30%的成绩信息
SELECT TOP(30) PERCENT 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
--同理 还有相同的
SELECT TOP(30) PERCENT WITH TIES 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
--先排序才会有TOP
SELECT 学号,课程编号,成绩 FROM 选课成绩
SELECT TOP(30) PERCENT 学号,课程编号,成绩 FROM 选课成绩
只是选出了在表上端的前30% 而不是真正的排名前30%
SELECT TOP(30) PERCENT 学号,课程编号,成绩 FROM 选课成绩 ORDER BY 成绩 DESC
真正要达到效果得先排序 同时也可以发现 语句是先进行排序再进行TOP函数的
mysql中无top用法
*分析语句执行顺序
理解了这些语句的查询顺序 才能对这个查询代码的编写更加清晰 所得的代码执行起来效率也会更高 是一个锦上添花的作用
首先
书写顺序应该是
Select……from……where……group by……having……order by……
这点熟悉了就知道
但是
在这里面其实有很多讲究
这一个个关键词是有执行顺序的
1、From
2、Where
3、Group by
4、Having
5、Select
6、Order by
简单理解就是:
从某张表中查询数据
先经过where条件筛选出有价值的数据
对这些有价值的数据进行分组
分组之后可以使用having继续筛选
Select把结果显示出来
最后排序输出
先分析第一个 from是最先执行的
这个显而易见
比如这样 select * from books 简单的一句查询
它的意思就是 从books里面找到所有数据 先from 再 select
select * from books where publisher='人民出版社'
在找到的这些数据里面 挑选符合条件的显示出来 from where select
1、2能不能颠倒?
select name from (select * from books where publisher='人民出版社')
这段语句是错的 它想表达的含义呢可能是 从找到的人民出版社的字段表中 找书名
那么是不是 from →where→select→from→select
错误的原因可能就在这 外层的from都还没执行 怎么可能执行了where和select操作
这个例子可能不太标准 也只是转个牛角尖去看1、2的顺序 其实1、2间没什么疑问
(这个问题只要加上别名就能解决 见后方子查询和别名的妙用)
3 group by一加入呢 疑问就多起来了
困扰我很久的几个问题也就在这一部分
比如 我找到出版社里 最贵的那本书的价钱 那我该怎么去知道这个最高的书是什么呢?
它不让我放进去啊!
为什么使用了分组 select后面的字段就只能是分组的字段和聚合函数 为什么聚合函数就能放进去
用执行顺序来分析一下 (from where groupby having select orderby)
先from 从books表里面取数据(此时数据未经筛选 就是一整个表)
Where没有
Group by 把这些数据按出版社进行分组 (此时数据变成了N条[跟出版社的数量有关])
重点!数据只有N条了 比如有3个出版社 现在等待被select的表里面的数据只有3条
但是!Name不止3个 假设books表中一共有10个名字 那我这10个名字怎么去跟预选的3个条数去对应?前三个名字分别对于这3个出版社?显然不合理 就算不报错也没有意义
意思就是name并没有参与分组 分组的只有publisher 他们的条目数量不匹配 因此无意义
那么为什么聚合函数就能放select后面
涉及到另外一个知识 就是聚合函数又叫做分组函数 它本是和分组相生的
那可能会有疑惑 我 select avg(price) from books 就可以执行啊 它又没group by分组
不不不 它是已经分了组的 不信可以试试这句 select avg(price),name from books
它又报错说name没有在聚合函数或者group by子句中
知识点来了 当聚合函数出现 又没有明确的group by子句时
它是默认把整个表分为一个组的 相当于group by 列1,列2…列n (所有列都放进去)
所以 聚合函数avg是参与了分组的 它的意思就是对这些已经分了组的数据 去求平均数
比如共3个出版社 出版社1有4本书 出版社2有3本书 出版社3有2本书
分完组是三条记录
第一条记录的第1列是出版社1 第2列就是4本书价钱加起来除以4
第二条记录……第三条……
他们的条目都是3 就没有什么不匹配、冲突的问题了
那么这个问题应该解决了
还有一个问题
Where子句里面为什么不能有聚合函数?
同样搬过来(from where group by having select order by)
分组是在where之后才会执行的 就是说 我先对一个数据进行筛选 对于这个已经where过的数据才去分组 这就涉及到它与having的区别 后面再分析
这个 select name from books where price>avg(price)
avg在where里面 可是where先执行 还没轮到分组呢 跟前面from where select 其实是一个道理 只是前面的那个更符合我们的认知 觉得不太可能 这个稍微隐晦些
就是一样的 当真正记住了、理解了这个执行过程 就会发现其实这个错误也很离谱
到了having
对于having 错误可能没太多因为跟正常人想法是差不多的 但是涉及到效率问题
顾名思义吗 having有 它执行顺序在group by后面 写法也是在group by后面(可能这也是不容易犯错的一个原因)
意味着 我要对分好组的这些数据 去做一个having 这些数据里“有”……
所以理解了 where在group by前 having在group by后吗 一个分组先筛选 一个分组后筛选
可能会疑惑 分组前筛选和分组后筛选有啥区别 不都一样
给出一个例子
要想查询 每个部门的最高薪资 要求显示最高薪资大于3000的
那么两种思路
光看题目跟着题目做的话 得到这样的语句
select deptno,max(sal) from emp group by deptno having max(sal)>3000
先分组 分组完之后 在每个组里分别找max 再去having筛选 最后才得到结果
不仅步骤多 数据量也大
那么另一种
select deptno,max(sal) from emp where sal>3000 group by deptno
先筛选出大于3000的 不满足的直接滚蛋 再对剩余的一部分数据分组 在里面去找max
这样一来 要处理的数据量就小了很多 步骤也变少了很多
这就是效率上面的区别
所以 where和having优先选择where where实在完成不了了 才用having
什么情况where实在完成不了?
比如 要对使用聚合函数之后的数据再进行操作的查询
查平均薪资大于2500的 select deptno,avg(sal) from emp group by deptno having avg(sal)>2500
还有要注意的一个 having不能单独存在 一定要和group by联合使用
Order by就查询完了 按一个顺序排序显示嘛 容易理解
关于这六条语句的执行顺序 存在的一些问题就都可以理解了
来个大杂烩
找出每个岗位的平均薪资 要求显示平均薪资大于1500的 除MANAGER岗位之外
要求按照平均薪资 按降序排
SELECT
Job,avg(sal) as avgsal
FROM
emp
WHERE
job!='MANAGER'
GROUP BY
job
HAVING
avg(sal)>1500
ORDER BY
avgsal desc;
还有一种关于使用别名来验证这些执行顺序的方法
看到过 但当时没太注意 找不到了
那个确实巧妙
这样也能理解 对于这个已经没啥问题了
就这段话:
从某张表中查询数据
先经过where条件筛选出有价值的数据
对这些有价值的数据进行分组
分组之后可以使用having继续筛选
Select把结果显示出来
最后排序输出
条例很清晰
老杜MYSQL P41~46也讲了这些问题
https://www.bilibili.com/video/BV1Vy4y1z7EX?p=48&vd_source=f90b3e1fec7a29aa578bf2c42517c160
还有 Distinct 也能用这种分析解释
select distinct 职称 from 教师 查有哪几种职称 假如1、2、3、4
select distinct 性别 from 教师 查有哪几种性别 男女
只保留一个 有相同就去掉
select distinct 性别,职称 from 教师 把性别和职称合并 两个都一样才叫重复
跟主键和唯一性约束很像
所以就不能 select 性别,distinct 职称 from 教师 会报错
Distinct 职称后 还剩4个字段 性别有多少个是跟表里面一样多的 它并没有去重
所以数量都不匹配 无意义 所以报错
💬 评论