Oracle 里的 分析函数

分析函数例子及讲解
SELECT emp.ename,
emp.sal,
emp.mgr,
row_number() over(PARTITION BY emp.mgr ORDER BY emp.sal DESC) row_number_dept, –部门排行
rownum row_number, –行号
ceil(rownum / 6) page,–每6行一页
ntile(2) over(ORDER BY emp.sa DESC) page_number_nt, –平均分成两类

   AVG(emp.salary) over(PARTITION BY emp.manager_id) avg_salary_department, --该部门薪水均值
   SUM(emp.salary) over(PARTITION BY emp.manager_id) sum_salary_department, --该部门薪水总额
   COUNT(emp.salary) over(PARTITION BY emp.manager_id) count_emp_department, --部门所有的员工
   dense_rank() over(PARTITION BY emp.manager_id ORDER BY emp.salary DESC) rank_salary_dept, --该人员的部门薪水排行
   dense_rank() over(ORDER BY emp.salary DESC) rank_salary_company, --该人员的全公司排行

   MIN(emp.salary) over(PARTITION BY emp.manager_id) min_salary_dept, --部门的最低薪水       
   MIN(emp.salary) keep(dense_rank FIRST ORDER BY emp.salary) over(PARTITION BY emp.manager_id) min_salary_dept_first, --部门的最低薪水
   first_value(emp.salary) over(PARTITION BY emp.manager_id ORDER BY emp.salary) min_salary_dept_firstv, --部门的最低薪水     

   MAX(emp.salary) over(PARTITION BY emp.manager_id) max_salary_dept, --部门的最高薪水 
   MAX(emp.salary) keep(dense_rank LAST ORDER BY emp.salary) over(PARTITION BY emp.manager_id) max_salary_dept_last, --部门的最高薪水 
   last_value(emp.salary) over(PARTITION BY emp.manager_id ORDER BY emp.salary) max_salary_dept_lastv, --部门的最高薪水

   lag(emp.full_name, 1, '00') over(ORDER BY emp.salary DESC) last_persion, --薪水在自己前一位的人
   lead(emp.full_name, 1, '00') over(ORDER BY emp.salary DESC) next_persion --薪水在自己后一位的人

FROM fwk_tbx_employees emp
ORDER BY emp.salary DESC
1. 基本概念理解

 分析函数
    1. 顾名思义,分析函数是在主查询结果的基础上进行一定的分析,如分部门汇总,分部门求均值等等。

 数据窗口
    1. Oracle 分析函数建立在所谓的数据窗口之上,数据窗口可以理解为一个数据集合。主查询的数据可以按照不同的标准分割成不同的数据集。比如partition BY manager_id 
 按照manager_id将主查询的数据分成N(N代表有多少个不同的Manager_id)个不同的数据窗口。
    2. 其次,数据窗口内部还应该与一定的顺序通过 ORDER BY 实现

 分析函数和GROUP BY的区别和联系
    1. 分析函数的功能大部分都可以通过GROUP BY 来聚合完成
    2. 分析函数查询出来的行数是由主查询决定的,GROUP BY 的行数结果是由GROUP BY 后面的集合构成的唯一性组合决定的,通常比主查询的结果行数少。
  1. 典型格式详解


    SUM(emp.salary) over(PARTITION BY emp.manager_id) sum_salary_department, –该部门薪水总额

    功能简介:
    当前行对应人员所在部门的薪水总额
    AVG,count与之类似

    过程理解

    1. 首先将查询出来的数据集按照MANAGER_ID分割
    2. 查找到当前行的MANAGER_ID对应的数据集
    3. 对以上数据集合求和,生成一个结果附在新添加的列中

 dense_rank() over(PARTITION BY emp.manager_id ORDER BY emp.salary DESC) rank_salary_dept, --该人员的部门薪水排行

功能简介:
当前行对应人员在所在部门的薪水排名(不出现并列情况,相同的值也会依次有不同的排序,且排序连续)
RANK 函数与之相反,要出现并列的情况啊,且并列将导致排名不连续如A和B并列第一,那么将没有第二名,而直接出现第三名
过程理解
1. 首先将查询出来的数据集按照MANAGER_ID分割
2. 对当前行MANAGER_ID对应的数据集进行排序
3. 将本行对应的行号提取并附在附加列中
—————————————————– MIN(emp.salary) keep(dense_rank FIRST ORDER BY emp.salary) over(PARTITION BY emp.manager_id) min_salary_dept_first, –部门的最低薪水

功能简介:
当前行对应人员在所在部门的最低薪水
MAX函数与之类似
过程理解
1. 首先将查询出来的数据集按照MANAGER_ID分割
2. 对当前行MANAGER_ID对应的数据集进行排序,提取最前面的行,最前面的行的值有相等的,那么返回多行
3. 在返回的多行中,提取薪水最小的行,并提取salary字段

DENSE_RANK是和KEEP结合使用的,网上给出的解释是Returns the row ranked first using DENSE_RANK,
即返回 DENSE_RANK函数的第一结果。
一般写法是 MIN [ MAX ] (A) KEEP(DENSE_RANK FIRST [ LAST ] ORDER BY B),解释一下:

DENSE_RANK
功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。
组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。
每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。
密集的序列返回的时没有间隔的数。

FIRST
功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),
因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

LAST
功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),
因此完整的语法需要在开始处加上一个集合函数以从中取出记录。
所以默认排序下,FIRST可以理解是取小值,LAST取大值。而前面的MIN或者MAX则是在KEEP的结果集中
取某一字段的最大值或最小值。


 first_value(emp.salary) over(PARTITION BY emp.manager_id ORDER BY emp.salary) min_salary_dept_firstv, --部门的最低薪水  

功能简介:
当前行对应人员在所在部门的最低薪水
last_value与之相反,求的是最后一个值

过程理解
1. 首先将查询出来的数据集按照MANAGER_ID分割
2. 对当前行MANAGER_ID对应的数据集进行排序
3. 提取第一行的salary字段


LAG(EMP.FULL_NAME, 1, ‘00’) OVER (ORDER BY EMP.SALARY DESC) LAST_PERSION, –薪水在自己前一位的人

功能简介:
总体薪水排名中,比自己高一位的人的名字
lead 函数与之相反求的在自己后面的人

参数介绍:
LAG(p_segment, p_distance, p_defaualt_val)
1. p_segment: 需要提取的字段
2. p_distance:>=0的数,表示比当前人员前面了几位
3. p_defaualt_val: 当当前行没有比它前的行的时候,显示默认值

过程理解
1. 首先将查询出来的数据集按照薪水进行降序排序
2. 提取前p_distance位的p_segment字段

PARTITION BY 可省略,但order by 不可省略
操作符 over(PARTITION BY deptno oeder by sal)

Select row_number()
over(PARTITION BY deptno oeder by sal)s1,
Rank() over(order by sal) s2,
Dense_rank() over(order by sal) s2 from emp;

猜你喜欢

转载自blog.csdn.net/weixin_42800008/article/details/82049311