SQL中row_number函数用法

row_number函数用法

1、函数讲解

语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)

简单的说,row_number()从1开始,为每条分组记录返回一个数字,举例:

ROW_NUMBER() OVER(ORDER BY xlh DESC)

这里的用法是先将xlh列进行降序排序,再将降序后的每条记录返回一个序号。
在这里插入图片描述

row_number() OVER (PARTITION BY COL1 ORDER BY COL2)
表示根据COL1分组,在分组内部根据COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)

初始数据显示为:
在这里插入图片描述
我们的目标是根据部门进行分组,并显示每个部门的工资等级
SQL语句:

select * ,Row_number() OVER(partition by deptid order by salary DESC) rank
FORM employee

最终显示结果为:
在这里插入图片描述

2、LeetCode实战

题目是LeetCode上的题目:
在这里插入图片描述
编写一个sql查询,查找所有至少连续出现三次的数字。返回的结果表中的数据可以按任意顺序排列。
查询格式如下面的例子所示:
在这里插入图片描述
下面是具体是解题代码:

select distinct Num as ConsecutiveNums from
(
    select Num,count(1) as SerialCount from
    (select id,Num,
        row_number() over(order by id) - 
        row_number() over(partition by Num order by Id) as SerialNumberSubGroup
        from Logs
    ) as sub 
    group by Num,SerialNumberSubGroup
    having count(1) >= 3
    
) as res

上面的解题是参照题解里以为大佬的解题思路:
具体解题过程参照:
作者:neilsons
链接:https://leetcode-cn.com/problems/consecutive-numbers/solution/sql-server-jie-fa-by-neilsons/
原始数据:
在这里插入图片描述

1、对原始数据编号,从1开始使用 row_number() over(表达式) 函数,使用Id来排序既row_number()

SELECT Id,Num,
row_number() over(order by id) as SerialNum
FROM ContinueNumber

在这里插入图片描述

2、使用原始数据另一维度排序,这些num值一样的分组排序,然后对其编号同样使用row_number() over(表达式),参数:(num分组,id排序)row_number() over(partition by num order by id)

SELECT Id,Num,
ROW_NUMBER() over(partition by Num order by Id) as SerialGroup
FROM ContinueNumber

在这里插入图片描述
3、通过上述1和上述2 看一下有什么规律吗?两个列(SerialNum,SerialGroup)对应相减,只要连续,相减得到的值是一样的。不连续相减得到的值也不同。

SELECT Id,Num,
      row_number() over(order by id) -
      row_number() over(partition by Num order by Id) as SerialNumberSubGroup
      FROM ContinueNumber

在这里插入图片描述

4、通过上述3,通过列Num和列SerialNumberSubGroup分组,最后拿到Num,就是求得的数据,去重(distinct)指:有可能同一个数字在多处出现三次以上。

SELECT DISTINCT Num FROM (
SELECT Num,COUNT(1) as SerialCount FROM 
(SELECT Id,Num,
row_number() over(order by id) -
ROW_NUMBER() over(partition by Num order by Id) as SerialNumberSubGroup
FROM ContinueNumber) as Sub
GROUP BY Num,SerialNumberSubGroup HAVING COUNT(1) >= 3) as Result

这个解题的核心是要想明白一个结论:如果一个num连续出现时,那么它出现的【真实序列】-它出现的次数一定是个定值。因为:

1、假设一个num出现后,它的 真实序列 为 i ,同时假设它是第 k 次出现的; 差值为 i-k.
2、当它连续出现一次时,它的 真实序列 一定为 i+1 ; 它的出现次数显然也会+1,为 k+1 ; 差值为 i+1-(k+1)=i-k.
3、当它连续出现第 n 次时,它的 真实序列 一定为 i+n;它出现的次数为 k+n;差值为 i+n-(k+n)=i-k.
4、如果它不连续出现,假设m个其他num出现之后,它又出现了,则它的真实序列为 i+n+m,而出现的次数为 k+n+1;差值为 i-k+m-1 。

所以,上述解题大佬的做法其实就是:
第一步重排的serialNum表示:这个num出现的真实序列,也就是说在原始数据中,它是第几个出现的;
第二步重排的serialGroup表示:这个num是第几次出现的;
然后其他的步骤就比较容易想了。

Guess you like

Origin blog.csdn.net/baidu_41797613/article/details/120489521