MySQL实现Oracle中的row_number over函数

update2020.9.11 Oracle的row_number over 该函数不确定在mysql8.0窗口函数是否支持,假如支持就不需要下面这种方式了。

1.首先了解Oracle中的row_number over 函数的作用就是按照某个字段进行分组,分组后再组内按照某个字段排序,且可以打印出一个新的排序的列。
2.MySQL是没有这个函数的,所以我们要想实现,则需要一些特殊方法。
需求如下:
表结构如下

CREATE TABLE `order` (
  `XXXX` varchar(10) DEFAULT NULL,
  `XXXX` varchar(10) DEFAULT NULL,
  `XXXX` varchar(3) DEFAULT NULL,
  `XXXX` varchar(100) DEFAULT NULL,
  `oprseq` varchar(100) DEFAULT NULL,
  `user_number` decimal(22,0) DEFAULT NULL,
  `XXXX` varchar(2) DEFAULT NULL,
  `order_id` bigint(20) DEFAULT NULL,
  `XXXX` date DEFAULT NULL,
  `XXXX` date DEFAULT NULL,
  `XXXX` tinyint(4) DEFAULT NULL,
  KEY `index_i` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

部分字段进行脱敏,我们关心的字段如下:
oprseq:订单序列号
user_number:用户手机号
order_id:订单号
要求是按照order_id asc limit1000条 其中手机号不能重复,假如有重复的,则取组内order_id最小的那个(asc)
处理sql如下:

select * from (
select @rownum:=@rownum+1 rownum,a.*,
    if(@userno=a.user_number or (@userno is null and a.user_number is null),
            @rank:=@rank+1,
            @rank:=1) as row_number,
    @userno:=a.user_number
    from(select * from
(select * from order  order by order_id asc limit 1000) d

order by  user_number,  order_id asc
) a,
    (select @rownum :=0,@userno:=null,@rank:=0)b) c
where row_number=1;

sql解释:
1.最内层的一个是按照索引进行一个排序的查询,select * from order order by order_id asc limit 1000,除非数据量非常大,否则这个sql会很快的。
2.(select * from (select * from order order by order_id asc limit 1000) d order by user_number, order_id asc),这个sql是对排序后的1000条数据按照手机号和订单号排序,这样就会把同样手机号的数据放在一起,方便后续对他们进行rank.
3.if(@userno=a.user_number or (@userno is null and a.user_number is null),
@rank:=@rank+1,
@rank:=1) as row_number,
@userno:=a.user_number
这个sql是实现row_number over功能的核心代码,if的作用为:if(condition,a,b),假如条件匹配,则a,否则则b,当然为了处理null的情况,所以又加了一个or 的条件去处理null的情况,上述代码意思是:假如@userno=该行的手机号,则rank+1,否则,rank就会赋值为1,体现到需求上,就是假如手机号有重复的,那么就会对重复的手机号进行累加,否则就对于每个不重复的手机号 rank赋值1 ,@userno本质上是查找这一行数据和上一行数据是否一致,因为在这个sql的后面会对@userno进行赋值,@userno:=a.user_number
4.(select @rownum :=0,@userno:=null,@rank:=0)b) 初始化sql,初始化几个变量的值
5.where row_number=1; 把组内得分第一的取出,其他的抛弃。

你可能感兴趣的:(MySQL实现Oracle中的row_number over函数)