数据库
首页 > 数据库> > mysql中这样解决数据排序和分组排序

mysql中这样解决数据排序和分组排序

作者:互联网

为大家熟知的关系型数据库有mysql、SQLServer、oracle、DB2等。它们的sql语句其实是有细微的差别的,不要想着有些语句在SQLServer上可以用就可以在mysql上使用。今天老韩就来讲一下其中的一个知识点,mysql中如何排名。

SQLServer和oracle中有row_num函数,可以对数据库中信息进行排名,但是mysql中却没有这个函数,那么在mysql中如何解决这个问题呢,下面老韩分为两块来讲解这个问题。

一、直接排序编号;

老韩想对student学生表中的学生按照score来进行排名,有些读者朋友说了,直接用order by一下不就完了,这样是按照成绩排名了,但是并没有编号,所以仅仅使用order by相当于需求实现了一部分,而且是很少的一部分,废话不多说直接上SQL语句:

set @nub:=0;

select (@nub:=@nub+1) as 排名,a.* from student a order by score;

执行结果:可以看到已经实现了需求,既排序了,又有了排名字段,咱们来分析一下SQL语句,set是赋值,还有一个赋值的关键字是select,但是使用select时候就不能直接将上面SQL语句中的set直接替换为select,因为select必须和select语句结合来使用,必须写成:select @nub:=@nub+1 as 排名,b.* from (select * from student ) b, (select @nub:=0) c order by score

“@”是声明变量的意思,除了“@”还有“@@”,两个@符号表示是全局变量,一个@符号表示局部变量,mysql中也可以使用declare声明变量,但是在这不可以使用,后面存储过程章节,老韩会讲,就跟Java中的new关键字一样,“:=”表示赋值,这个地方等同于“=”,由于“:=”比“=”使用范围广泛,统一使用“:=”即可,@nub:=@nub+1表示@nub先+1再赋值给@nub,这个地方是前面老韩讲过的虚拟列,这里不多做赘述。

二、分组后再排序编号;

直接上SQL语句,老韩再针对SQL语句进行分析,SQL语句:

select

@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno

from

(select b.* from (select distinct classno from student order by classno)a left join student b on a.classno = b.classno) c ,(select @nub:=0, @classnoCopy:=0 )d

查询结果为:如下图所示,可以看到实现了我们的需求。

先对学生进行分组再通过score来排名,老韩针对上面的sql语句来进行一个分析,分析一个sql语句的时候先从内往外分析,因为执行的时候也是从内而外,有人会问你为啥知道,如果内部不执行,外部如何查数据,肯定是内部先出来数据之后,外部才能去查。

最下面的别名为d的数据集,这个地方前面已经讲过,声明两个变量并赋值。

别名为c的数据集,这里面有个关键字distinct,表示去重,实际上不写也没问题但是老韩为了更明显就写了,表示取student表中所有的班级编号并去重,加上left join表示以班级为主表来进行数据填充,因为老韩又加了order by classno表示升序排列,那么所有的信息都会以这个顺序去匹配,效果如下图所示;

加上left join之后的效果如下图所示,如果不能理解为什么是这种效果可以查看前面的左连接、右连接章节,其实这个地方完全可以写成select username,classno,score from student order by classno,这里是赶巧了可以直接使用order by,如果是字符串就不好说了。

最关键的地方来了,@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno这两句代码如何理解呢?我们要明确一点,sql执行就想Java程序main方法中代码执行一样,从上到下去执行,先执行@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名。

这里面有个case when 语句,读者朋友不要懵逼,这个东西其实我们前面学过的,它表示当classnoCopy=classno返回true的时候@nub=@nub+1,else就是返回false,@nub=1,最后以end结尾,表示语句结束,是不是跟三元运算非常相似啊,其实mysql中也有三元运算但是写法跟Java中不一样,所以上面的语句可以写成这样:@nub:=if(@classnoCopy=classno,(@nub+1),1),if(),瓜号内有三个变量,第一个变量就是表达式,返回一个boolean类型,后面跟两个值,如果是true就返回第一个值,如果false就返回第二个值。

sql语句执行是从这一句开始执行的,可以看到,刚开始@classnoCopy是0,很明显跟班级编号不一样,那么这个时候排名等于1,开始执行下面的语句,下面的语句是赋值,将classno赋值给@classnoCopy,sql语句是一行一行对结果集进行扫描的,到第二行的时候,@classnoCopy=classno很明显是成立的,所以排名会加1变成2,扫描第三行的时候@classnoCopy=classno不成立了,因为这个时候@classnoCopy是1,classno是2,排名又变成了1,循环执行语句就得到需要的结果。

标签:语句,classnoCopy,分组,mysql,classno,排序,nub,select
来源: https://www.cnblogs.com/lpc-work/p/14774940.html