vlambda博客
学习文章列表

关于oracle和mysql数据库的查询问题

近期在写mysql数据库报表时,需要给查询排序后的数据增加一列序号,用来统计查询数据的排名,在这里遇到一个视图和排序冲突的问题。


Part 1


oracle数据库中可以直接给查询语句增加一列ROWNUM, ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说 rownum 是对符合条件结果的序列号,它总是从1开始排起。


比如sql如下

select rownum,t.* from table t;

但是以上sql如果不增加排序,这个数据没有问题,一旦增加排序,序列号就会错乱。

select rownum,t.* from table t order by t.stamp


▷ 第一种解决办法:增加一个子查询

select  rownum,a.*  from (select t.* from table t order by t.stamp)  a


▷ 第二种解决办法:使用row_number()函数

select row_number() over (order by t.stamp) rn,t.*  from table t


原理:会先对stamp进行排序,排序完后,再给每条数据进行编号。


row_number() over()函数是一个强大的分组排序函数,在使用 row_number() over()函数时候,over()里头的分组以及排序的执行晚于 where 、group by、  order by 的执行。



Part 2


但在使用mysql数据库时,这些函数和办法都无法使用,mysql数据库给查询增加一个序列就需要用到参数,最简单的办法如以下sql:


SELECT @rownum:=@rownum+1 AS 序号, t.* FROM  table t,(SELECT @rownum:=0) r 

设定一个参数为0,使每行增加1,作为第一列的序列号。


还可以使用以下几种写法

① select (@rowNO := @rowNo+1) AS rowno,a.* from (SELECT * FROM t_user) a,(select @rowNO :=0) b ;

②set @rn=0; select @rn:=@rn+1 as rn, m.* from (select * from t_user  )m; -- 连续执行两个语句

③ select (@rowNO := @rowNo+1) AS 序号,a.* from  t_user a,(select @rowNO :=0) b


注意:@rownum的写法不唯一,但一定有@,等于号写法一定是:=(冒号等于)


这种方式的查询存在的问题是语句中存在参数和子查询,在需要建立视图时会出现报错,mysql不允许视图语句中有参数和子查询语句。会出现报错:

1351 - View's SELECT contains a variable or parameter


在需要排序增加排名并建立查询视图的情况下,可以使用以下这种办法:

SELECT (SELECT COUNT(*)+1 FROM table  b WHERE b.排序字段 > a.排序字段) AS row_num, a.* FROM  table  AS a;


上面的sql语句可以达到在mysql数据库中建立视图的要求,但由于是通过比对字段大小来达成目的,如果排序字段这一列列数据中存在相同的值则会出现两个排名相同的行。