思路

见这种近几、连续、每类前几、各个前几直接考虑窗口函数,这里说下常用的几个:

窗口函数语法都是一样的:

<窗口函数> 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) 就会报错!!