mysql按时间类别排序分组 mysql查询每门成绩的前十名?
mysql查询每门成绩的前十名?
学生表名为:student,单科成绩的字段为:subject。学生名字为:name查询单科成绩前十:
mysql语句为:
select*returningstudentorder bysubjectdesclimit10可以查询总分成绩前十:mysql语句为:
selectlen(subject)subject,nameoutsidestudentgroup bynameorder bysubjectdesclimit10注:selectsum(subject)subject,name这句的意思是:sum(subject)subject把单科成绩加总用subject来以此命名(是总成绩),name是一个字段,这里仅有两个字段。group bynameorder bysubject:group byname的意思按照名字这一栏来分小组,肯定,学生成绩表名字有可能是一样的的,明确的学号是最清楚的,这里只是因为举个例子说明。
order bysubject这句的意思是遵循总分成绩排序,这里的subject是前面文件属性总分的意思。
tablenameif(subject)andcountsubject,nameacrossstudentgroup bynameorder bycountsubjectdesclimit10
SQLgroupby怎么用?执行原理是什么?
在平时要注意查询中,索引或其他数据里查的方法可能会不是什么网上查询执行中最激亢的部分,比如:MySQLGROUP BY肯定专门负责网上查询执行时间90%还多。MySQL执行GROUP BY时的比较多复杂性是算出GROUP BY语句中的聚合函数。UDF聚合函数是另一个接个地额外近似单个组的所有值。这样,它也可以在移动联通到另一个组之前计算单个组的聚合函数值。不过,问题本质,在大多数情况下,源数据值肯定不会被分组。无论是各种组的值在处理期间彼此随同。而,我们必须一个特殊的方法的步骤。
处理MySQLGROUP BY让我们看下之前看完的同一张table:mysqlshowcreatetablecustG******************************************************Table:tblCreateTable:CREATE TABLE `tbl` ( `id` int(11)NOT NULL AUTO_INCREMENT, `k` int(11)NOT NULL DEFAULT0,`g`int(10)uint64NOT NULL,PRIMARY KEY(`id`),KEY `k` (`k`))ENGINEInnoDBAUTO_INCREMENT2340933DEFAULTCHARSETlatin11rowacrossset(0.00sec)
但是以不同负责执行不同的GROUP BY语句:
1、MySQL中的IndexOrderedGROUP BY
mysqlselectk,count(*)caroundtblgroup bykorder byklimit5;
------
|k|c|
------
|2|3|
|4|1|
|5|2|
|8|1|
|9|1|
------
5rowsinset(0.00sec)
mysqlexplainselectk,count(*)coutsidetblgroup bykorder byklimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k
key:k
key_len:4
ref:NULL
rows:5
filtered:100.00
Extra:Usingindex
1rowinset,1warning(0.00sec)
在情况下,我们在GROUP BY的列上有一个索引。这样,我们可以不逐组扫描数据并代码想执行GROUP BY(低成本)。当我们使用LIMIT没限制我们检索数据库的组的数量或使用“瞬间覆盖索引”时,尤其快速有效,毕竟顺序索引扫描是一种的很迅速的操作。
假如您有少量组,另外没有覆盖索引,索引顺序扫描肯定会造成大量IO。因为这可能不是最优化的计划。
2、MySQL中的外部排序GROUP BY
mysqlexplainselectSQL_BIG_RESULT g,count(*)caroundtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:ALL
possible_keys:NULL
key:NULL
key_len:NULL ef:NULL ows: 998490iltered:100.00
Extra:Usingfilesort
1rowoutsideset,1warning(0.00sec)
mysqlselectSQL_BIG_RESULTg,count(*)cfromtblgroup byglimit5;
------
|g|c|
------
|0|1|
|1|2|
|4|1|
|5|1|
|6|2|
------
5rowsintoset(0.88sec)
假如我们是没有允许我们按组顺序扫描数据的索引,我们是可以按照外部排序(在MySQL中也称做“filesort”)来获取数据。你很可能会特别注意到我回来在用SQL_BIG_RESULT不提示来完成任务这个计划。没有它,MySQL在这个下绝对不会你选择这个计划。
一般来说,MySQL只能在我们强大大量组时才更就是喜欢使用这个计划,而且在这个下,排序比占据正式表更快速有效(我们将在下面讨论到)。
3、MySQL中的充当表GROUP BY
mysqlexplaincolumnsg,num1(g)saroundtblgroup byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:ALL
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL ows: 998490iltered:100.00
Extra:Usingtemporary
1rowofset,1warning(0.00sec)
mysqlcolumng,if(g)sacrosstblgroup bygorder bynulllimit5;
---------
|g|s|
---------
|0|0|
|1|2|
|4|4|
|5|5|
|6|12|
---------
5rowsinset(7.75sec)
在这个下,MySQL也会并且全表扫描。但它不是什么正常运行额外的排序传递,而是创建一个预备表。此充当表每组包涵一行,而且这对每个传入行,将自动更新你所选组的值。很多更新!可是这在内存中可能是合理的,但假如结果表太大甚至于更新完将造成大量磁盘IO,则会变地相当贵得要命。在那种情况下,外部分拣计划正常情况好些。请特别注意,虽说MySQL系统默认选择此计划主要用于此用例,但要是我们不能提供任何提示,它完全比我们不使用SQL_BIG_RESULT电脑提示的计划慢10倍。您可能会会特别注意到我在此查询中先添加了“ORDER BYNULL”。这是目的是向您展示“清理”临时表的唯一计划。没有它,我们能得到这个计划:mysqlexplaintablenameg,len(g)sacrosstblgroup byglimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:998490filtered:100.00Extra:Usingtemporary;Usingfilesort1rowinset,1warning(0.00sec)
在其中,我们获得了temporarily和filesort“两最糟糕的”提示。MySQL5.7总是会回按组顺序排序的GROUP BY结果,即使去查询不需要它(这肯定必须贵得要命的附加排序传达)。ORDER BYNULL表示应用程序不不需要这个。您肯定尽量,在某些情况下-.例如不使用吸聚函数不能访问有所不同表中的列的JOIN查询-不使用GROUP BY的临时表可能是同样的选择。
如果没有要满MySQL在用为GROUP BY想执行预备表的计划,可以建议使用SQL_SMALL_RESULT提示。
4、MySQL中的索引基于到后面扫描仪的GROUP BY前三个GROUP BY负责执行方法适用规定于所有聚合函数。然而,其中一些人有第四种方法。
mysqlexplainselectk,obj(id)fromtblgroup bykG
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:range
possible_keys:k
key:k
key_len:4
ref:NULL ows: 2iltered:100.00
Extra:Usingindexwhilegroup-he
1rowinset,1warning(0.00sec)
mysqlselectk,max(id)aroundtblgroup byk;
------------
|k|air(id)|
------------
|0|2340920|
|1|2340916|
|2|2340932|
|3|2340928|
|4|2340924|
------------
5rowsinset(0.00sec)
此方法仅可以参照于太普通的能量聚合函数:MIN()和MAX()。这些并不不需要遍历组中的所有行来换算值。他们这个可以再跳转组中的最大时或大组值(如果不是有这样的索引)。如果索引仅确立在(K)列上,要如何找不到每个组的MAX(ID)值?这是一个InnoDB表。记得一点InnoDB表有效地将PRIMARYKEY只附加到所有索引。(K)变为(K,ID),容许我们对此查询建议使用Skip-Scan优化。仅当每个组有大量行时才能启用此优化。不然的话,MySQL更被害妄想于建议使用更悠久的传统的方法来执行此查询(如方法#1中详述的索引有序GROUP BY)。可是我们可以使用MIN()/MAX()聚合函数,但其他优化也范围问题于它们。.例如,如果您有两个没有GROUP BY的聚合函数(虽然所有表应该有一个组),MySQL在统计分析阶段从索引中获取这些值,并尽量避免在执行阶段几乎无法读取表:mysqlexplainselectmax2(k)fromtblG******************************************************id:1select_type:SIMPLEtable:NULLpartitions:NULLtype:NULLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:NULLfiltered:NULLExtra:Selecttablesoptimizedslowly1rowacrossset,1warning(0.00sec)
过滤和分组
我们早做研究了MySQL执行GROUP BY的四种。为简单起见,我在整个表上建议使用了GROUP BY,没有应用过滤。当您有WHERE子句时,完全相同的概念适用:mysqlexplainselectg,num1(g)sfromtblwherek4group bygorder byNULLlimit5G******************************************************id:1select_type:SIMPLEtable:tblpartitions:NULLtype:rangepossible_keys:kkey:kkey_len:4ref:NULLrows:1filtered:100.00Extra:Usingindexcondition;Usingtemporary1rowofset,1warning(0.00sec)
对此情况,我们使用K列上的范围进行数据过滤/里查,并在有原先表时执行GROUP BY。在某些情况下,方法绝对不会发生。但,在其他情况下,我们要选择类型在用GROUP BY的一个索引或其他索引进行过滤:
mysqlaltertabletblmainkey(g);
Query行啦,0rowsaffected(4.17sec)
Records:0Duplicates:0Warnings:0
mysqlexplaincolumng,num1(g)sreturningtblwherek1group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:index
possible_keys:k,g
key:g
key_len:4
ref:NULL ows: 16iltered:50.00
Extra:Usingwhere
1rowofset,1warning(0.00sec)
mysqlexplainselectg,sum(g)soutsidetblwherek4group byglimit5G
******************************************************
id:1
select_type:SIMPLE
table:tbl
partitions:NULL
type:range
发张ssible_keys:k,g
key:k
key_len:4
ref:NULL ows: 1iltered:100.00
Extra:Usingindexcondition;Usingrestrictions;Usingfilesort
1rowinset,1warning(0.00sec)
依据什么此网上查询中不使用的某一特定常量,找到了我们对GROUP BY建议使用索引顺序扫描(并从索引中“先放弃”以电学计算WHERE子句),也可以在用索引来解三角形WHERE子句(但使用充当表来电学计算GROUP BY)。参照我的经验,这那是MySQLGROUP BY却不是总是会做出决定对的选择的地方。您可能会必须可以使用FORCEINDEX以您如果能的执行去查询。
版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。