思路
见这种近几、连续、每类前几、各个前几直接考虑窗口函数,这里说下常用的几个:
窗口函数语法都是一样的:
<窗口函数> OVER (partition by <用于分组的列名> order by <用于排序的列名>)
序号函数:row_number、rank、dense_rank
为了方便我在这里就简单化了,也就是说对100,99,99,85,84
row_number的进行排序结果是:1、 2、 3、 4 、5
rank的排序结果是:1、2、2、4、5
dense_rank的排序结果是:1、2、2、3、4
ROW_NUMBER()函数可以理解为排序号,不考虑并列;
RANK()函数也为排号,考虑并列,并列之后的按照实际序号来;
dense_rank()同样是排号,考虑并列,并列之后按下一个名次来。
分布函数:percent_rank()/cume_dist()
percent_rank()
用途:和之前的RANK()函数相关,每行按照如下公式进行计算:(rank - 1) / (rows - 1) 其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。
cume_dist()
用途:分组内大于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。 应用场景:班级中比当前同学成绩高的学生比例是多少
前后函数: lag() / lead()
将该字段/列的前n行(lag)、后n行(lead)提取出来
用途:分组中位于当前行后n行(lead)/ 前n行(lag)的记录值。 应用场景:求每个用户相邻两次浏览的时间差
lead(score,1)即 将score字段的后一列列出来
lag(score,1)即 将score字段的前一列列出来
头尾函数——first_val(expr) / last_val(expr)
用途:得到分区中的第一个/最后一个指定参数的值。
nth_value(expr, n)
用途:返回窗口中第N个expr的值,expr可以是表达式,也可以是列名
聚合函数
都知道所以就不说了
现在应该清楚这个题为什么是dense_rank,
所以我们为什么不用distinct先进行去重,再用row_number呢?
这就关系到distinct本身的用法:
distinct
select distinct一起出现!!!!!除非聚合函数!!!
也就是说你要么只查一个、要么多列去重!!
select distinct(name1) , name2,name3
并不会仅对括号内的列进行去重,而是依旧对 distinct 后面的所有列进行组合去重
也就是1=2=3的时候才会去重!
而如果
select name, name3 , distinct(name1) 就会报错!!