order by语句,SQL里面的order by语句是干什么用的?
order by语句,SQL里面的order by语句是干什么用的?详细介绍
本文目录一览: sql 升序降序排列
降序
SELECT * FROM kc ORDER BY cpbh DESC
升序
SELECT * FROM kc ORDER BY cpbh asc
实例:
/*查询学生表中姓名、学号,并以学号降序排序*/
select name,StuID from Students_information order by StuID desc /**order by 以什么排序,默认为升序,desc是降序*/
/*查询学生表中前5名学生的姓名,学号,并以学号升序排列*/
select top 5 name,StuID from Students_information order by StuID /*order by 默认为升序*/
扩展资料
ORDER BY 语句:
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照升序对记录进行排序。
实例:
1,AddTime 升序,ID 升序
select * from DS_Finance ORDER BY AddTime,ID;
2,AddTime 升序,ID降序
select * from DS_Finance ORDER BY AddTime,ID DESC;
3,AddTime 降序,ID升序
select * from DS_Finance ORDER BY AddTime DESC,ID ;
4,AddTime 降序,ID降序
select * from DS_Finance ORDER BY AddTime DESC,ID DESC;
参考资料:百度百科-结构化查询语言
降序
SELECT *
FROM kc
ORDER BY cpbh DESC
升序
SELECT *
FROM kc
ORDER BY cpbh asc
order by + 表中的某一列 + ASC(升序)/DESC(降序)
desc 为降序 asc为升序,默认为升序
降序:SELECT * FROM kc ORDER BY cpbh DESC
升序:SELECT * FROM kc ORDER BY cpbh ASC
语法:
sql可以根据字段进行排序,其中,DESC表示降序,ASC表示升序
order by 字段名 DESC;按照字段名降序排序
order by 字段名 ASC;按照字段名升序排序
实例:
一、/*查询学生表中姓名、学号,并以学号降序排序*/
select name,StuID from Students_information order by StuID desc /**order by 以什么排序,默认为升序,desc是降序*/
二、/*查询学生表中前5名学生的姓名,学号,并以学号升序排列*/
select top 5 name,StuID from Students_information order by StuID /*order by 默认为升序*/
扩展资料:
一、ORDER BY 语句
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
二、SQL 排序多个字段
order by 多个字段,每个字段后面都有排序方式,默认ASC
例如:select table a order by a.time1 ,a.time2 desc,a.time3 asc
参考资料:w3school-SQL ORDER BY 子句
sql语句时间排序 sql语句按照时间排序
SQL按时间排序 select * from MyTable Order By ModifyTime Desc
按修改的时间倒序排列
如果是知道最后一次是某天,加上条件
select * from MyTable Where DateDiff(day,ModifyTime,GetDate)=0 Order By ModifyTime Desc
sql 排序,order by 按时间 sql排序是指定时间字段才能按照时间排序,asc默认升序,desc默认降序。
ORDER BY 语句
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
比如要排序:
select date from tablename order by date desc
按date降序排列。
SQL语句怎么写?先按时间排序,再按姓名排序? 将字段依次写在order by 后面即可 , 中间用逗号隔开
select * from 表 order by time , name
select * from 表 order by time asc , name asc
select * from 表 order by time desc , name desc
select * from 表 order by time asc , name desc
select * from 表 order by time desc , name asc
(注: asc 表示升序 , desc表示降序 , 未明确写明排序方式时默认是升序 )
与之类似的语法是 group by , 按多个字段分组时 , 也是依次将多个字段写在group by 的后面 , 并用逗号隔开 , 范例如下:
select time , name , sum(*) from 表 group by time , name
怎样用SQL语句 按日期进行从高到低进行排序 用SQL语句按日期进行从高到低进行排序:select * from tmp order by time desc;
结构化查询语言(英文简称:SQL)是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同 数据库系统,,可以使用相同的结构化查询语言作为数据输入与管理的接口。结构化查询语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。
标签:作文经典 上一篇:带苦干的词语 形容苦干的词语 下一篇:快板台词护士夸赞美 夸赞幼儿园快板台词 sql语句的根据日期排序问题! 这个问题的原因是你的time 不是datetime 应该是varchar型.
改成这个.
sql="select id,title,content,class,img,time from info order by cast(time as datetime) desc"
就行了
怎样用SQL语句 按日期进行从高到低进行排序呢~~ 就是对日期进行倒排序
select * from tableName -- 假设你的表的名字是tableNameorder by dtcol desc; -- 假设你的日期字段名是 dtcol; desc表示倒排序
sql语句:请问下面这sql怎么往上加排序(降序)以时间为降序? 你这样查询出来就一个 符合你条件的记录数
没办法排序啊?
如果打算按时间排序就别查个数了。。
select refund_id,addtime from refund where refund_audit=1 and f_user_uid ='" + userid + "'
order by addtime desc
//按时间倒叙
sql语句怎么按照字段1排序后再在本字段内按时间排序 ORDER BY 后面可以写多个
比如
ORDER BY Gender ASC, Age DESC, Name ASC
按照性别升序排列, 性别相同的按照年龄降序排列, 年龄再相同的按照姓名升序排列
SQL语句排序的问题 升序是 ASC,降序是 DESC
select * FROM a ORDER BY 锭 ASC,n DESC
sql 日期正序 时间倒序 这个问题,因为你日期和具体时间分别在两列上,因此,是可以采用sql实现的。
SQL中增加order by语句如下:
ORDER BY 日期, 时间 DESC
如果你的这两个列有些特殊性,或者两个列没有分开,可以单独联系,我帮你解决(相对来说复杂点)
标签:作文经典 上一篇:带苦干的词语 形容苦干的词语 下一篇:快板台词护士夸赞美 夸赞幼儿园快板台词
若sql语句中order by指定了多个字段,则怎么排序?
举个例子吧:
order by id desc,time desc
先是按 id 降序排列 (优先)
如果 id 字段 有些是一样的话 再按time 降序排列 (前提是满足id降序排列)
依次按自左至右的字段顺序排序
order by id desc,time desc
先是按 id 降序排列 (优先)
如果 id 字段 有些是一样的话 再按time 降序排列 (前提是满足id降序排列)
order by name, age desc
name优先
name一样的话,就按age排序。
后面再加第三列的话,也是一样 以此类推下去。
扩展资料:mySql order by 几种排序的写法
1、单列升序:select
from
sql中order by和group by的区别
order by 和 group by 的区别:
1,order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。
2,group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
3,在使用group by的语句中,只能select用于分类的列(表达式),或聚合函数。where条件用于group by之前,having用于group by 之后对结果进行筛选。
扩展资料:
一、order by用法: 排序查询、asc升序、desc降序
示例:
1.select * from 学生表
2.order by 年龄
3.查询学生表信息、按年龄的升序(默认、可缺省、从低到高)排列显示也可以多条件排序、 比如 order by 年龄,成绩 desc
4.按年龄升序排列后、再按成绩降序排列。二、group by用法: 分组查询、having 只能用于group by子句、作用于组内,having条件子句可以直接跟函数表达式。使用group by 子句的查询语句需要使用聚合函数。
示例:
1.select 学号,SUM(成绩) from 选课表 group by 学号 按学号分组、查询每个学号的总成绩
2.select 学号,AVG(成绩) from 选课表
3.group by 学号
4.having AVG(成绩)>(select AVG(成绩) from 选课表 where 课程号='001')
5.order by AVG(成绩) desc
6.查询平均成绩大于001课程平均成绩的学号、并按平均成绩的降序排列。
参考资料:
百度百科- 结构化查询语言
1、适用范围不同:
order by 用于排序,一般与asc升序或desc降序一起使用。例如select * from 表A order by 列a。group by 用于分类汇总,一般与聚合函数一起使用。
2、定义不同:
order by主要侧重许多数据的排序,例如按照大小顺序对数据进行排列,group by主要侧重许多数据的分组,例如按照性别、年龄、国家、学科等进行分组。
3、主要用途不同:
order by 是按表中某字段排列表中数据。group by 是按某些字段分类。
扩展资料
order by的用法:
首先,order by是用来写在where之后,给多个字段来排序的一个DQL查询语句。
其次,order by写法:
1、select 字段列表/* from 表名 where 条件 order by 字段名1 asc/desc, 字段名2 asc/desc,.......
2、select 字段列表/* from 表名 where 条件 order by 字段序号 asc/desc, 字段序号 asc/desc,.......(此时字段序号要从1开始)
然后,order by的方式:
1、asc 升序,可以省略,是数据库默认的排序方式。
2、desc 降序,跟升序相反。
最后要注意order by的原则,写在最前面的字段,他的优先级最高,也就是写法中第一个的字段名1的优先级最高,优先执行他的内容。
1、解释不同:
(1)order by是SQL语句中的关键字,用于对查询结果的排序。ORDER BY 语句用于对结果集进行排序,默认的为升序。
(2)group by语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”。它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理。
2、字段不同:
(1)order by是按字段排序,后面必须列出排序的字段名,可以是多个字段名。
(2)group by是按字段分类 ,必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
3、sql命令格式优先顺序不同:
(1)group By关键字先对指定的分组条件将筛选得到的视图进行分组,将分组视图后不满足条件的记录筛选掉。
(2)order By语句最后对视图进行排序,最终的结果就产生了。
4、引用列名不同:
(1)order by语句中引用列名可以使用IDE。
(2)group by需要引用列名则只能使用ID,而不能使用IDE。
5、排序方法不同:
(1)order by 语句默认按照升序对记录进行排序。
(2)group by语句指定的列对满足Where条件的所有记录分组,并对组内的一些数值型栏位计算出每组的一个统计指标,如求和、求个数、求平均值、求最大值、求最小值等等。
6、查找范围不同:
(1)order by子句能用于查找组记录特征和某条记录的详细信息;
(2)group by子句只能用于查找组记录特征,但不能查找某条记录的详细信息。Group By + [分组字段](可以有多个)。在执行了这个操作以后,数据集将根据分组字段的值将一个数据集划分成各个不同的小组。
7、使用的函数不一样:
(1)order by放在from table_name后面。可以用于根据指定的列asdf对结果集进行排序。按照降序对记录进行排序,可以使用 DESC 关键字。
(2)group by子句中可使用的函数AVG() 、MIN() 、 MAX() 、SUM() 、COUNT() 。group by all 语句是不能和CUBE 和 ROLLUP 关键字一起使用的。使用 GROUPING 函数确定结果集内的空值是否是 GROUP BY 汇总值。
扩展资料:一、GROUP BY 和 ORDER BY一起使用时,ORDER BY要在GROUP BY的后面。
group by a,b,c;则a,b,c三个字段是按照先按a字段对数据行进行排序,再按b字段对那些字段a为同一个值的数据行进行排序,再再按c字段对那些字段a为同一个值且字段b为同一个值的数据行进行排序。
二、Group By, Having, Where, Order by几个语句的执行顺序。
一个SQL语句往往会产生多个临时视图,以上列举的关键字是按照如下顺序进行执行的:Where, Group By, Having, Order by。
1、首先where将最原始记录中不满足条件的记录删除(所以应该在where语句中尽量的将不符合条件的记录筛选掉,这样可以减少分组的次数);
2、然后通过Group By关键字后面指定的分组条件将筛选得到的视图进行分组;
3、接着系统根据Having关键字后面指定的筛选条件,将分组视图后不满足条件的记录筛选掉;
4、然后按照Order By语句对视图进行排序,这样最终的结果就产生了。
在这四个关键字中,只有在Order By语句中才可以使用最终视图的列名。
参考资料来源:百度百科-GROUP BY参考资料来源:百度百科-order by
order by 是按表中某字段排列表中数据。
group by 是按某些字段分类。
以下是详细区别:
1、排序方式不一样:
order by是指按字段排序;
group by是指按字段分类 。
2、命令格式优先顺序不一样:
order by要滞后;
group by要优先。
3、含义不一样:
Group By是分组的意思,Order By是按顺序的意思。
4、使用的函数不一样:
Group By是汇总查询,使用时至少需要一个分组标志字段,一般与聚合函数(比如sum合计、count计算行、avg平均)一起使用。
Order By是排序查询,用于对指定列结果集的排序,排序内容可以是数字或者文字,其中DESC是降序,ASC是升序。
5、定义不一样:
order by主要侧重许多数据的排序,例如按照大小顺序对数据进行排列;
group by主要侧重许多数据的分组,例如按照性别、年龄、国家、学科等进行分组。
扩展资料:SQL使用技巧代码大全:
1、编辑
1=1,1=2的使用在SQL语句组合时用的较多,“where 1=1”是表示选择全部 “where 1=2”全部不选。
如:if @strWhere !='begin
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere
end else begin set @strSQL = 'select count(*) as Total from [' + @tblName + ']' end
set @strSQL='select count(*) as Total from tablename where 1+1'
if(@strWhere!='')
{set @strSQL=@strSQL+’and’+strWhere}
2、收缩数据库
(1)重建索引 :
DBCC REINDEX
DBCC INDEXDEFRAG
(2)收缩数据和日志:
DBCC SHRINKDB
DBCC SHRINKFILE
(3)压缩数据库:
dbcc shrinkdatabase(dbname)
(4)转移数据库给新用户以已存在用户权限:
exec sp_change_users_login 'update_one','newname','oldname' go
(5)检查备份集:
RESTORE VERIFYONLY from disk='E:\dvbbs.bak'
(6)修复数据库:
Alter DATABASE [dvbbs] SET SINGLE_USER GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK GO
Alter DATABASE [dvbbs] SET MULTI_USER GO
参考资料来源:百度百科-SQL语句大全百度百科-结构化查询语言
区别:order by是排序,group by是分组。
order by:默认是ASC,按升序排列,DESC降序排列。order by执行后会进行全表扫描,降低性能,如果数据量特别大的时候,要排序的话尽量按照组合索引中的字段进行order by。
group by:把相同的列放到一组。group by的实现过程除了要使用排序操作外,还要进行分组操作。group by操作想要利用索引,必须满足group by字段必须同时存放于同一个索引中,且该索引是一个有序索引,而且,使用不同的聚合函数也会影响是否使用索引来实现group by操作。
扩展资料:
order by 后面可以跟多个字段,优先级按先后顺序。
group by 后面要搭配聚合函数一起使用,没有在group by后的字段,select的时候必须使用聚合函数(sum,count,max,min)。group by 可以和having一起使用来对数据过滤,having后面也必须是聚合函数。如:select no,count(1) from test group by no having count(1) > 1。
1、意思不一样。
order by 是指从英文里理解就是行的排序方式,默认的为升序。后面必须列出排序的字段名,可以是多个字段名。
group by 是指从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
2、适用范围不同:order by 用于排序,一般与asc升序或desc降序一起使用。例如select * from 表A order by 列a。
group by 用于分类汇总,一般与聚合函数(比如avg平均、sum合计、max最大、min最小、count计算行)一起使用。例如select 月份,sum(工资)as 总工资 from 工资表 group by 月份。
3、定义不同:order by主要侧重许多数据的排序,例如按照大小顺序对数据进行排列,group by主要侧重许多数据的分组,例如按照性别、年龄、国家、学科等进行分组。
4、使用的函数不一样。
order by子句中的列必须包含在聚合函数或 GROUP BY 子句中。
group by 子句中可使用的函数AVG() 、MIN() 、 MAX() 、SUM() 、COUNT() 。
5、order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。
group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
扩展资料
Microsoft Jet 数据库引擎 SQL 数据类型 由13个基本数据类型组成,它们是由 Microsoft Jet 数据库引擎和几个验证过的有效同义字定义的。常见的有:整形,单精度,双精度,可变长度字符,固定长度字符,长型,日期等等。
可以用ALTER TABLE 语句修正基数和增量。刚插进表中的行会有自动为基于新种值和增量值的列生成的值。如果新种和增长的值和以前的种值及增量匹配,就会造成复制。如果这个列是主键,复制值生成时可能导致错误。
定义成TEXT也称作MEMO)或CHAR(也称作有具体长度的 TEXT(n))的字段中的字符被储存在 Unicode 表示格式。
Unicode字符一律需要两个字节存储每一字符。对于现有的主要包含字符数据的 Microsoft Jet数据库,这可能意味着数据库文件被转换成 Microsoft Jet 4.0格式时字长会增加将近一倍。
然而,从前由单字节字符群(SBCS)指示的众多字符群的Unicode 表示可以很容易地被压缩成一个单字节。有关的详细信息,参见CREATE TABLE。如果用COMPRESSION属性定义CHAR列,数据存储时会自动被压缩,提取时解压缩。
参考资料来源:百度百科-SQL数据类型
SQL里面的order by语句是干什么用的?
order by为排序表达式,用于指定排序的依据,它可以是字段名也可以是字段别名。
例--.对成绩表先按课程编号,再按成绩,然后按学号排列
select *
from 成绩表
order by 课程编号,成绩,学号
--.查询成绩表中成绩最高的前五条记录,显示与第五条成绩相同的记录
select top 5 with ties *
from 成绩表
order by 成绩 desc
ASC和DESC用于指定排序方式。前者指定字段的值按照升序排列,后者按照降序排列,默认顺序为升序。
sql 排序,order by 按时间
你这个是字符吧?字符当然10<11<8<9了
1. 把时间类型改成date类型之类的
2. 进行用字符存储,把8:30改成08:30,9:30改成09:30存储
order by (CAST(LEFT(字段名,CHARINDEX(':',字段名)-1) AS INT))
别忘了评为最佳,谢谢
sql排序是指定时间字段才能按照时间排序,asc默认升序,desc默认降序。
ORDER BY 语句
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
比如要排序:
select date from tablename order by date desc
按date降序排列。
SQL里面的order by语句是干什么用的?
order by为排序表达式,用于指定排序的依据,它可以是字段名也可以是字段别名。
例--.对成绩表先按课程编号,再按成绩,然后按学号排列
select *
from 成绩表
order by 课程编号,成绩,学号
--.查询成绩表中成绩最高的前五条记录,显示与第五条成绩相同的记录
select top 5 with ties *
from 成绩表
order by 成绩 desc
ASC和DESC用于指定排序方式。前者指定字段的值按照升序排列,后者按照降序排列,默认顺序为升序。
排序
order by 字段 这样是降排序
order by 字段 desc 这样是降排序
SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?
SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序? 先进行分组处理。 Group By 和 Having, Where ,Order by这些关键字是按照如下顺序进行执行的:Where, Group By, Having, Order by。
首先where将最原始记录中不满足条件的记录删除(所以应该在where语句中尽量的将不符合条件的记录筛选掉,这样可以减少分组的次数) 然后通过Group By关键字后面指定的分组条件将筛选得到的检视进行分组
接着系统根据Having关键字后面指定的筛选条件,将分组检视后不满足条件的记录筛选掉 最后按照Order By语句对检视进行排序,这样最终的结果就产生了。 在这四个关键字中,只有在Order By语句中才可以使用最终检视的列名,如:
SELECT FruitName, ProductPlace, Price, ID AS IDE, Discount FROM T_TEST_FRUITINFO WHERE (ProductPlace = N'china') ORDER BY IDE 这里只有在ORDER BY语句中才可以使用IDE,其他条件语句中如果需要引用列名则只能使用ID,而不能使用IDE。
SQL语句中,有group by 和order by两个语句,是先分组还是先排序? 肯定是group by先 order by优先顺序最低,在最后 group by 语句执行后记录会按关键字自动升序? 不一定,group by只负责分组。
VF 中先排序order by还是先分组 group by 这是需要看题上的要求,要求要分组才分组,要求要排序才排序的,并不是每道题两个都同时需要
sql语句中 order by 排序原则 ORDER BY这个指令来达到我们的目的。 ORDER BY 的语法如下: SELECT "栏位名" FROM "表格名" [WHERE "条件"] ORDER BY "栏位名" [ASC, DESC] [] 代表 WHERE 是一定需要的。不过,如果 WHERE 子句存在的话,它是在 ORDER BY 子句之前。 ASC 代表结果会以由小往大的顺序列出,而 DESC 代表结果会以由大往小的顺序列出。如果两者皆没有被写出的话,那我们就会用 ASC。 我们可以照好几个不同的栏位来排顺序。在这个情况下, ORDER BY 子句的语法如下(假设有两个栏位): ORDER BY "栏位一" [ASC, DESC], "栏位二" [ASC, DESC] 若我们对这两个栏位都选择由小往大的话,那这个子句就会造成结果是依据 "栏位一" 由小往大排。若有好几笔资料 "栏位一" 的值相等,那这几笔资料就依据 "栏位二" 由小往大排。
select-sql 语句中,筛选用(?)子句,分组用group by 子句,排序用order by 子句 筛选用 where 子句
比如 select * from sutdent where 年龄=20 这就是根据年龄这个条件进行筛选
oracle sql语句中 先执行where还是order by where 里面条件 and 是先执行 and 前面 还是后面条件这个其实和你写的顺序不大,这个先后顺序,是资料库来根据表/索引的资讯来决定的。例如一个 学生表, 有学号,姓名,性别其中 学号是主键, 姓名上面有个索引。 找 名字叫 强妹 的女生: SELECT * FROM 学生 WHERE 姓名='强妹' AND 性别 = '女' 与 SELECT * FROM 学生 WHERE 性别 = '女' AND 姓名='强妹' 资料库在处理 SQL 以前,都会去分析, 发现 查询的条件中, 姓名上面有索引,而性别上面没有。 那么优先根据 姓名的条件, 去检索,然后再去把通过索引得到的资料,去筛选 性别=女的比如表里面共有10000行。姓名叫 '强妹' 的只有一个。那么通过索引,一步就定位到那一行。然后再判断这一行资料的 性别栏位, 是不是 = '女' 假如 姓名/性别 都没有索引呢?那就是执行 全表扫描。不分先后。什么意思呢?就是假如 表里面10000行资料。那就是从第一行开始, 检视 姓名与性别 条件。 满足的返回。 不满足的丢弃。 直到100行都处理完。并不是一口气把所有的资料,都放到记忆体里面,然后 姓名判断一次, 去掉部分, 性别判断一次,再去掉部分。 蓝屏
sql语句中的where语句和order by语句,哪个语句先执行 ④SELECT [DISTINCT] * | 列 [别名],列 [别名],…… ①FROM 表名称 [别名],表名称 [别名],…… ②[WHERE 限定条件] ③[GROUP BY 分组栏位,[分组栏位,分组栏位……]] ⑤[ORDER BY 排序列名 [ASC|DESC],排序列名 [ASC|DESC],……]
where先执行:SQL语句执行顺序:SELECTFROM--1WHERE--2GROUPBY--3HAVING--4ORDERBY--5
where先执行,然后对筛出来的结果再排序。 如果不先按where查出来的结果再排序,那先排序出来的结果有什么意义呢。
对order by的理解
前言
日常开发中,我们经常会使用到order by,亲爱的小伙伴,你是否知道order by 的工作原理呢?order by的优化思路是怎样的呢?使用order by有哪些注意的问题呢?本文将跟大家一起来学习,攻克order by~
一个使用order by 的简单例子
假设用一张员工表,表结构如下:
表数据如下:
我们现在有这么一个需求:查询前10个,来自深圳员工的姓名、年龄、城市,并且按照年龄小到大排序。对应的 SQL 语句就可以这么写:
这条语句的逻辑很清楚,但是它的底层执行流程是怎样的呢?
order by 工作原理
explain 执行计划
我们先用Explain关键字查看一下执行计划
我们可以发现,这条SQL使用到了索引,并且也用到排序。那么它是怎么排序的呢?
全字段排序
MySQL 会给每个查询线程分配一块小内存,用于排序的,称为 sort_buffer。什么时候把字段放进去排序呢,其实是通过idx_city索引找到对应的数据,才把数据放进去啦。
我们回顾下索引是怎么找到匹配的数据的,现在先把索引树画出来吧,idx_city索引树如下:
idx_city索引树,叶子节点存储的是主键id。还有一棵id主键聚族索引树,我们再画出聚族索引树图吧:
我们的查询语句是怎么找到匹配数据的呢?先通过idx_city索引树,找到对应的主键id,然后再通过拿到的主键id,搜索id主键索引树,找到对应的行数据。
加上order by之后,整体的执行流程就是:
执行示意图如下:
将查询所需的字段全部读取到sort_buffer中,就是全字段排序。这里面,有些小伙伴可能会有个疑问,把查询的所有字段都放到sort_buffer,而sort_buffer是一块内存来的,如果数据量太大,sort_buffer放不下怎么办呢?
磁盘临时文件辅助排序
实际上,sort_buffer的大小是由一个参数控制的:sort_buffer_size。如果要排序的数据小于sort_buffer_size,排序在sort_buffer 内存中完成,如果要排序的数据大于sort_buffer_size,则借助磁盘文件来进行排序
如何确定是否使用了磁盘文件来进行排序呢?可以使用以下这几个命令
可以从 number_of_tmp_files 中看出,是否使用了临时文件。
number_of_tmp_files 表示使用来排序的磁盘临时文件数。如果number_of_tmp_files>0,则表示使用了磁盘文件来进行排序。
使用了磁盘临时文件,整个排序过程又是怎样的呢?
TPS: 借助磁盘临时小文件排序,实际上使用的是归并排序算法。
小伙伴们可能会有个疑问,既然sort_buffer放不下,就需要用到临时磁盘文件,这会影响排序效率。那为什么还要把排序不相关的字段(name,city)放到sort_buffer中呢?只放排序相关的age字段,它不香吗?可以了解下rowid 排序。
rowid 排序
rowid 排序就是,只把查询SQL需要用于排序的字段和主键id,放到sort_buffer中。那怎么确定走的是全字段排序还是rowid 排序排序呢?
实际上有个参数控制的。这个参数就是max_length_for_sort_data,它表示MySQL用于排序行数据的长度的一个参数,如果单行的长度超过这个值,MySQL 就认为单行太大,就换rowid 排序。我们可以通过命令看下这个参数取值。
max_length_for_sort_data 默认值是1024。因为本文示例中name,age,city长度=64+4+64 =132 < 1024, 所以走的是全字段排序。我们来改下这个参数,改小一点.
使用rowid 排序的话,整个SQL执行流程又是怎样的呢?
执行示意图如下:
对比一下全字段排序的流程,rowid 排序多了一次回表。
什么是回表?拿到主键再回到主键索引查询的过程,就叫做回表”
我们通过optimizer_trace,可以看到是否使用了rowid排序的:
全字段排序与rowid排序对比
一般情况下,对于InnoDB存储引擎,会优先使用全字段排序。可以发现 max_length_for_sort_data 参数设置为1024,这个数比较大的。一般情况下,排序字段不会超过这个值,也就是都会走全字段排序。
order by的一些优化思路
我们如何优化order by语句呢?
联合索引优化
再回顾下示例SQL的查询计划
我们给查询条件city和排序字段age,加个联合索引idx_city_age。再去查看执行计划:
可以发现,加上idx_city_age联合索引,就不需要Using filesort排序了。为什么呢?因为索引本身是有序的,我们可以看下idx_city_age联合索引示意图,如下:
整个SQL执行流程变成酱紫:
流程示意图如下:
从示意图看来,还是有一次回表操作。针对本次示例,有没有更高效的方案呢?有的,可以使用覆盖索引:
覆盖索引:在查询的数据列里面,不需要回表去查,直接从索引列就能取到想要的结果。换句话说,你SQL用到的索引列数据,覆盖了查询结果的列,就算上覆盖索引了。”
我们给city,name,age 组成一个联合索引,即可用到了覆盖索引,这时候SQL执行时,连回表操作都可以省去啦。
调整参数优化
我们还可以通过调整参数,去优化order by的执行。比如可以调整sort_buffer_size的值。因为sort_buffer值太小,数据量大的话,会借助磁盘临时文件排序。如果MySQL服务器配置高的话,可以使用稍微调整大点。
我们还可以调整max_length_for_sort_data的值,这个值太小的话,order by会走rowid排序,会回表,降低查询性能。所以max_length_for_sort_data可以适当大一点。
当然,很多时候,这些MySQL参数值,我们直接采用默认值就可以了。
使用order by 的一些注意点:没有where条件,order by字段需要加索引吗
日常开发过程中,我们可能会遇到没有where条件的order by,那么,这时候order by后面的字段是否需要加索引呢。如有这么一个SQL,create_time是否需要加索引:
无条件查询的话,即使create_time上有索引,也不会使用到。因为MySQL优化器认为走普通二级索引,再去回表成本比全表扫描排序更高。所以选择走全表扫描,然后根据全字段排序或者rowid排序来进行。
如果查询SQL修改一下:
分页limit过大时,会导致大量排序怎么办?
假设SQL如下:
索引存储顺序与order by不一致,如何优化?
假设有联合索引 idx_age_name, 我们需求修改为这样:查询前10个员工的姓名、年龄,并且按照年龄小到大排序,如果年龄相同,则按姓名降序排。对应的 SQL 语句就可以这么写:
我们看下执行计划,发现使用到Using filesort
这是因为,idx_age_name索引树中,age从小到大排序,如果age相同,再按name从小到大排序。而order by 中,是按age从小到大排序,如果age相同,再按name从大到小排序。也就是说,索引存储顺序与order by不一致。
我们怎么优化呢?如果MySQL是8.0版本,支持Descending Indexes,可以这样修改索引:
使用了in条件多个属性时,SQL执行是否有排序过程
如果我们有联合索引idx_city_name,执行这个SQL的话,是不会走排序过程的,如下:
但是,如果使用in条件,并且有多个条件时,就会有排序过程。
这是因为:in有两个条件,在满足深圳时,age是排好序的,但是把满足上海的age也加进来,就不能保证满足所有的age都是排好序的。因此需要Using filesort。