OVER(PARTITION BY) 函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OVER(PARTITION BY) 函数相关的知识,希望对你有一定的参考价值。

参考技术A 最近在项目中遇到了对每一个类型进行求和并且求该类型所占的比例的需求。
一开始使用的是自表的连接,后来发现这样做太复杂,更改后的SQL的解决方法是:

注意:在求第一名成绩的时候,不能用 row_number() ,因为如果同班有两个并列第一, row_number() 只返回一个结果。

结果为:

可以看出,本来第一名是两个人的并列,结果只显示了一个。

(2). rank() 和 dense_rank() 可以将所有的都查找出来, rank 可以将并列第一名的都查找出来; rank() 和 dense_rank() 区别: rank() 是跳跃排序,有两个第二名时接下来就是第四名。

求班级成绩排名:

查询结果:

dense_rank() 是连续排序,有两个第二名时仍然跟着第三名

查询结果:

(3). sum() over() 的使用
根据班级进行分数求和

(4). first_value () over() 和 last_value() over() 的使用

分别求出第一个和最后一个成绩。

(5). sum() over() 的使用

求出班级的总分。

下面还有很多用法,就不一一列举了,简单介绍一下,和上面用法类似:

(6). over partition by 与 group by 的区别:
group by 是对检索结果的保留行进行单纯分组,一般和聚合函数一起使用例如 max 、 min 、 sum 、 avg 、 count 等一块用。 partition by 虽然也具有分组功能,但同时也具有其他的高级功能。

Orcale分析函数OVER(PARTITION BY... ORDER BY...)的讲解

顾名思义,PARTITION 中文是分割的意思,ORDER 是排序的意思,所以翻译一下就是先把一组数据按照制定的字段进行分割成各种组,然后组内按照某个字段排序。

以实际案例来说明这个函数的使用,

首先,我们先看一组普通排序的数据:

技术分享图片

然后对其进行新加一个伪劣ROWNUM,看看数据原本的顺序:

技术分享图片

OVER(ORDER BY ...)的意思是以按照某个字段排序,所以和直接对表的order by效果是一样的:

技术分享图片

这里就显示了OVER(ORDER BY ...)的第一个功能,就是对新查询得到的数据进行重新编号,即RNO的值,由于这里没有PARTITION BY...,所以可以比作整个列就是一个大块,然后对大块的内容进行排序,这个时候再加上PARTITION BY...,查询结果:

技术分享图片

它会按照制定的字段,把相同值的排在一起,分为一个块,也就是分组,然后组内排序编号,这样你就可以取不同组内的任意第几个值,类似于TOP-N的分析。

在这里over之前使用的函数是ROW_NUMBER(),就是对数据的编号。

 

与OVER(PARTITION BY... ORDER BY...)匹配使用的函数

row_number() over()、rank() over()和dense_rank() over()

在上面的例子里,使用ROW_NUMBER()可以对数据编号,但是有一个问题,例子中的MI_ID是不可以重复的,如果在可以重复的情况下,就有并列的情况,这样就无法取出并列的数据,只能取单一排序的数据。所以这里可以换成 rank() over()和dense_rank() over()来进行编号:(rank() over()和dense_rank() over()的区别如图)

技术分享图片

技术分享图片

sum() over(),first_value() over()和last_value() over()的使用

sum() over()分组求和

first_value() over()求分组第一条

last_value() over()求分组最后一条

其中用row_number() over()取编号第一条的也可以实现first_value() over()的效果

SELECT DISTINCT *
  FROM (SELECT T1.MI_ID,
               T3.I_IDENTITY_CARD,
               SUM(NVL(T2.IS_VISHEARTPROMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) PRO_NUM,
               SUM(NVL(T2.IS_VISHEARTEXPMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) EXP_NUM,
               SUM(NVL(T2.IS_VISHEARTPOLMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) POL_NUM,
                             T1.CREATE_TIME,
               FIRST_VALUE(T2.CREATE_DATE) OVER(PARTITION BY T3.I_IDENTITY_CARD ORDER BY T2.CREATE_DATE DESC) FIRST_CREATE_DATE
          FROM T_ZZ_PETITIONERS T1
          LEFT JOIN T_ZZ_VISIT_RECORD T2
            ON T1.CI_RS_ID = T2.CI_RS_ID
           AND T2.STATUS != 003
          LEFT JOIN T_DC_CI_RS_TOP T3
            ON T1.CI_RS_ID = T3.CI_RS_ID
           AND T3.STATUS = 1
         WHERE T1.IS_ADD_HEARTPROTECT = 1
           AND T1.STATUS = 1) C
 ORDER BY C.CREATE_TIME DESC

 

技术分享图片

 

 

SELECT *
  FROM (SELECT T1.MI_ID,
               T3.I_IDENTITY_CARD,
               SUM(NVL(T2.IS_VISHEARTPROMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) PRO_NUM,
               SUM(NVL(T2.IS_VISHEARTEXPMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) EXP_NUM,
               SUM(NVL(T2.IS_VISHEARTPOLMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) POL_NUM,
               T1.CREATE_TIME,
               ROW_NUMBER() OVER(PARTITION BY T3.I_IDENTITY_CARD ORDER BY T2.CREATE_DATE DESC) RNO
          FROM T_ZZ_PETITIONERS T1
          LEFT JOIN T_ZZ_VISIT_RECORD T2
            ON T1.CI_RS_ID = T2.CI_RS_ID
           AND T2.STATUS != 003
          LEFT JOIN T_DC_CI_RS_TOP T3
            ON T1.CI_RS_ID = T3.CI_RS_ID
          LEFT JOIN T_DC_GRID T4
            ON T1.REGION_CODE = T4.INFO_ORG_CODE
         WHERE T1.IS_ADD_HEARTPROTECT = 1
           AND T1.STATUS = 1
           AND T3.STATUS = 1
           AND T4.STATUS = 001) C
 WHERE C.RNO = 1
 ORDER BY C.CREATE_TIME DESC

 

技术分享图片

 

ignore nulls:过滤掉空值

 

常用的分析函数如下所列:

row_number() over(partition by ... order by ...)
rank() over(partition by ... order by ...)
dense_rank() over(partition by ... order by ...)
count() over(partition by ... order by ...)
max() over(partition by ... order by ...)
min() over(partition by ... order by ...)
sum() over(partition by ... order by ...)
avg() over(partition by ... order by ...)
first_value() over(partition by ... order by ...)
last_value() over(partition by ... order by ...)
lag() over(partition by ... order by ...)
lead() over(partition by ... order by ...)

 

本文转自:https://blog.csdn.net/east_mrchiu/article/details/70183428














以上是关于OVER(PARTITION BY) 函数的主要内容,如果未能解决你的问题,请参考以下文章

ROW_NUMBER() OVER()函数用法;(分组,排序),partition by

ROW_NUMBER() OVER()函数用法;(分组,排序),partition by

ROW_NUMBER() OVER()函数用法;(分组,排序),partition by

oracle分析函数over partition by 和group by的区别

hive开窗函数over(partition by ......)用法

Orcale分析函数OVER(PARTITION BY... ORDER BY...)的讲解