让我们一起聊聊“窗口函数”

在上篇的经典实例中,遇到了一种情形:查询每门功课成绩最好的前两名,说实话,一开始,我就进入了误区,很自然而然地使用了县排序后top或者Limit的思维,可是始终得不到想要的查询结果,哎,在对函数了解得不够多的情况下,去想使用一些常见的函数来解决的过程真的很伤脑啊,但是,经过查询资料发现,此处如果使用窗口函数OverROW_Number()Partition by是非常容易解决的,那么而接下来,让我们脚踏实地地来看下,这是如何实现的——————

窗口函数

所谓窗口函数,顾名思义就是替下一步查询打开了一扇“窗”,采用官方术语来讲,就是对一组值进行操作,不需要使用Group by子句对数据进行分组,还能在同一行返回基础行的列和使用聚合函数得到的聚合列。此处重点就在于,在同一行返回基础行的列和聚合后的列,对于基础行和聚合列查询特别简单。

语法格式

在oracle中,一般分为内置over子句中和内置Window子句中,针对上篇遇到的问题,此刻,就单纯地聊下over()。

OVER([PARTITION BY value_expression,..[n] ] <ORDER BY BY_Clause>)

ROW_Number()

返回结果集内的行号,每个分区从1开始计算,ORDER BY可确定在特定分区中为行分配唯一 ROW_NUMBER 的顺序。

SELECT * FROM(SELECT *,ROW_number() over(PARTITION by cid ORDER BY score DESC) AS od FROM SC)t1 WHERE od<=2;

让我们一起聊聊“窗口函数”_第1张图片

让我们一起聊聊“窗口函数”_第2张图片

看完我们上次遇到的问题,接下来,让小编带你再补充一下其他的函数————

Rank()

返回结果集的分区内每行的排序。行的排名是从1开始算。如果两个或多个行与一个排名关联,则每个关联行将得到相同的排名,也就是说可以有相同的排名。

例如:

 SELECT RANK() OVER(PARTITION BY Name ORDER BY SCORE) ,Score, Name, CreateTime
  FROM SC

让我们一起聊聊“窗口函数”_第3张图片

DESN_RANK()

返回结果集分区中行的排名,与Rank()类似,只是对并列的处理不同。

例如:

SELECT DENSE_RANK() OVER(PARTITION BY Name ORDER BY SCORE) ,Score, Name, CreateTime
FROM SC

让我们一起聊聊“窗口函数”_第4张图片

小提示

窗口函数一般不适用Group by的原因在于此时要分清Group by和Partition by的区别,其实实质就在于Partition by 是对表的横向分区,比如一门课程可以有很多学生选修,那么对于这个每一个课程id都可以进行分成不同的区,每个区包含选修的学生信息,如果想要知道每门课程的前几名,那么此时就很方便的对每个区进行排序,而如果是Group by ,那么只能对整张表的课程进行排序,并不能排除有学生在不同的课程排名相同的情形,而且Group by使用具有限制性,只能和聚合函数一起使用。

上述如有错,请指正,谢谢!

你可能感兴趣的:(数据库)