美文网首页
MySQL实现Oracle中的row_number over函数

MySQL实现Oracle中的row_number over函数

作者: frankie_cheung | 来源:发表于2020-09-01 10:17 被阅读0次

    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函数

          本文链接:https://www.haomeiwen.com/subject/piwmsktx.html