分析函数

这里的分析函数也就是我们常说的开窗函数,通常有两类:

一类是聚合开窗函数(SUM、AVG、MAX、MIN、COUNT等),

一类是排序开窗函数(ROW_NUMBER、DENSE_RANK、RANK等)。

本文主要内容转自《高效使用Greenplum》一书。

分析函数是Greenplum数据库管理系统自带函数中的一种专门解决具有复杂统计需求的函数,它可以对数据分组,然后基于组中数据进行分析统计,最后在每组数据集的每一行返回这个统计值。

分析函数不同于分组统计(Group By),分组统计只能按照分组字段返回一个固定的统计值,不能在原来的数据行上附带这个统计值,而分析函数正式专门解决这类统计需求所开发出来的函数。分析函数已经逐步称为SQL标准的一部分,有越来越多的数据库系统开始支持分析函数。

开窗函数和聚合函数的区别如下:

  • SQL 标准允许将所有聚合函数用作开窗函数,用OVER 关键字区分开窗函数和聚合函数。
  • 聚合函数每组只返回一个值,开窗函数每组可返回多个值。

分析函数的语法结构如下:

SELECT table.column,

analysis_function() OVER ( [PARTITION BY 字符] [ORDER BY 字段 [rows]] ) as 统计值

FROM table

其中:

analysis_function():指定分析函数名称,常用的分析函数有sum、max、first_value、last_value、lag、lead、rank、desn_rank、row_number等。

OVER():开窗函数名,PARTITION BY指定进行数据分组的字段,ORDER BY指定进行排序的字段,ROWS指定数据窗口(即指定分析函数要操作的行数),语法形式为OVER(PARTITION BY xxx ORDER BY yyy ROWS BETWEEN zzz)。

这里的ROWS有多个范围值(一般情况下会省略),具体如下:

  1. unbounded preceding:无限/不限定往前的范围;
  2. n preceding:往前统计n行;
  3. unbounded following:无限/不限定往后的范围;
  4. n following:往后统计n行;
  5. current row:当前行;

案例:下图是员工表和部门表数据内连接后的结果集。

select b.dept_id,b.dept_name,t.emp_id,t.emp_name,t.age,t.salary

from emp t,dept b

where t.dept_id = b.dept_id

dept_id

dept_name

emp_id

emp_name

age

salary

1100

销售部

3

Jack

40

15000

1100

销售部

4

Michael

36

9800

1200

研发部

2

Alen

29

13500

1200

研发部

5

Lily

36

12500

1110

销售一部

6

David

30

7900

1120

销售二部

7

Timmy

26

8500

1000

总裁办

1

Paul

45

36000

案例1:利用min(),max()分析函数分别取出不同部门不同员工工资的最高值和最低值,附带在原始数据上。

select b.dept_id,b.dept_name,t.emp_id,t.emp_name,t.age,t.salary

-- 获取组中工资最高值

max(t.salary) OVER(PARTITION BY t.dept_id) AS salary_max,

-- 获取组中工资最低值

min(t.salary) OVER(PARTITION BY t.dept_id) AS salary_min,

-- 分组窗口的第一个值(指定窗口为组中第一行到末尾行)

first_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_first,

-- 分组窗口的最后一个值(指定窗口为组中第一行到末尾行)

last_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_last,

-- 分组窗口的第一个值(不指定窗口)

first_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC) AS salary_first_1,

-- 分组窗口的最后一个值(指定窗口才可以取到最低值,否则只能取到当前行)

last_value(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS salary_last_1

from emp t,dept b

where t.dept_id = b.dept_id

order by t.dept_id,t.emp_id

根据查询结果可以看出如下信息:

min()和max()分析函数直接获取组中最小值和最大值;

first_value()和last_value()返回窗口的第一行和最后一行数据,因为我们通过工资字段对分组内的数据进行了降序排列,所以也可以达到在一定的窗口内获取最大值和最小值的功能;

排序不指定窗口时,就按照组内的第一行到当前行作为窗口,然后取出窗口的第一行和最后一行;

窗口子语句当中的第一行是UNBOUNDED PRECEDING,当前行是CURRENT ROW,最后一行是UNBOUNDED FOLLOWING,正是利用窗口范围是第一行到最后一行,得到同一部门内的最高工资和最低工资。

注意:ROWS的默认值是:BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。

案例2:利用rank()、dense_rank()、row_number()函数对员工的年龄进行排序,比较三个不同关键字的差异。

select t.emp_id,t.emp.name,t.age,

row_number() OVER(ORDER BY t.age) AS “row_number排名”,

rank() OVER(ORDER BY t.age) AS “rank排名”,

dense_rank() OVER(ORDER BY t.age) AS “dense_rank排名”

from emp t

order by t.age

根据查询结果可以看出如下信息:

emp_id

emp_name

age

row_number

rank

dense_rank

7

Timmy

26

1

1

1

2

Alen

29

2

2

2

6

David

30

3

3

3

4

Michael

36

4

4

4

5

Lily

36

5

4

4

3

Jack

40

6

6

5

1

Paul

45

7

7

6

row_number()函数排名返回唯一值,当遇到相同的数据时,排名按照记录集中的记录顺序依次递增;

rank()函数返回唯一值,当遇到相同的数据时,所有相同的数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名;

dense_rank()函数返回唯一值,当遇到相同的数据时,所有相同数据的排名是一样的,同时在最后一条相同记录和下一条不同记录的排名之间不空出排名。

案例3:利用开窗函数对员工工资进行不同条件的汇总,以便对比ORDER BY和PARTITION BY的作用。

select t.emp_id,t.emp_name,t.age,t.salary,

sum(t.salary) OVER() AS “全局汇总”,

sum(t.salary) OVER(ORDER BY t.emp_id) AS “逐行累加”,

sum(t.salary) OVER(PARTITION BY t.dept_id) AS “分组汇总”,

sum(t.salary) OVER(PARTITION BY t.dept_id ORDER BY t.emp_id) AS “分组逐行汇总”

from emp t

order by t.emp_id

根据查询结果可以看出如下信息:

OVER()默认是全局汇总,即所有可以查到的行数指标合集,可用于计算占比;

OVER+ORDER BY用于根据条件逐行相加汇总,可用于计算类似于“工资占前80%的员工明细”之类的需求;

OVER+PARTITION BY用于分组汇总,可以计算分组的合计、分组的占比、分组的最大值和最小值等;

OVER+PARTITION BY+ORDER BY用于分组逐行汇总,可用于计算分组的排名,可以满足例如“取每一个组的前五名”之类的需求;

案例4:查询部门总工资大于所有部门平均总工资的部门员工信息及部门平均工资、公司平均工资。

select * from (

select emp_id,emp_name,dept_id,salary,

avg(salary) OVER(PARTITION BY dept_id) as dept_avg_salary,

avg(salary) OVER() as comp_avg_salary

from emp) t

where t.dept_avg_salary > t.comp_avg_salary;

【学习笔记】分析函数(开窗函数)相关推荐

  1. SQLServer sql学习笔记(开窗函数,连接,四舍五入,分页,聚合函数等)

    一.四舍五入 1. Round(@num,2)   保留两位有效数字,四舍五入但不去掉零 2.Convert(decimal(18,2),@num) 3.cast(@num as decimal(18 ...

  2. Hive学习笔记三之函数操作

    文章目录 5 函数 5.1 系统内置函数 5.2 常用内置函数 5.2.1 空字段赋值 5.2.2 CASE WHEN THEN ELSE END(类似于java中的switch case) 5.2. ...

  3. c++学习笔记内联函数,函数重载,默认参数

    c++学习笔记内联函数,函数重载,默认参数 1 inline内联函数 C++中的const常量可以替代宏常数定义,如: const int A = 3;  #define A 3 C++中是否有解决 ...

  4. c语言中void arrout,c语言学习笔记(数组、函数

    <c语言学习笔记(数组.函数>由会员分享,可在线阅读,更多相关<c语言学习笔记(数组.函数(53页珍藏版)>请在人人文库网上搜索. 1.数组2010-3-29 22:40一维数 ...

  5. IOS学习笔记07---C语言函数-scanf函数

    2013/8/7 IOS学习笔记07---C语言函数-scanf函数 ------------------------------ qq交流群:创梦技术交流群:251572072            ...

  6. IOS学习笔记07---C语言函数-printf函数

    IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...

  7. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

  8. oracle分析函数-开窗函数

    oracle分析函数 分析函数是什么? 分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值. ...

  9. jquery学习笔记及常用函数封装

    二.JQuery 学习笔记及常用函数封装 https://download.csdn.net/download/weixin_42530002/13087988 1.JQuery入门 (1).css选 ...

  10. STATA学习笔记:egen函数

    STATA学习笔记:egen函数 1. egen (1)mean() webuse egenxmpl,clear egen avg = mean(cholesterol) gen deviation ...

最新文章

  1. 开源超美css动态背景 可直接引入html文件使用 含注释、可更改
  2. 硬链接和软链接使用,以及区别
  3. 运维经验分享(六)-- 深究crontab不能正确执行Shell脚本的问题(二)
  4. vue 报错./lib/html5-entities.js, this relative module was not found
  5. boost::noncopyable用法的测试程序
  6. python生活中哪些运用_【想把python运用在实际生活中?那么python查询价格方法可以帮助你】- 环球网校...
  7. dna编码库_Nature |DNA元件百科全书(ENCODE)计划, 全面注释基因组元件
  8. java 前端导出exvel_java导出数据到Excel文件 前端进行下载
  9. 计算机机房的维护管理论文,学校计算机机房维护与管理论文
  10. 关于 jquery和js获取宽度时只能取整数,取不到小数点
  11. Python之路-4
  12. kelley c语言教程 机械工业出版社,北京工业大学2020年考研893软件工程学科专业基础考试大纲...
  13. 李阳疯狂英语学习方法大全集-英语,单词
  14. java http 传输二进制流_文件以二进制流POST的HTTP请求
  15. ma5671怎么设置_华为MA5671怎样设置POE供电
  16. 使用conda时出现Solving environment: failed with initial frozen solve. Retrying with flexible solve错误
  17. 英语水平测试项目----总结遇到的问题
  18. html实现多图片上传并预览,【前端预览】实现多张上传图片预览查看
  19. html实现滑块拖动验证
  20. python strip函数

热门文章

  1. System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.
  2. IE8 能否再创辉煌?
  3. 真正的职场强者,都是闭环主义高手
  4. 线上分享 | 价值与风险,像投资者一样做产品决策
  5. 腾讯产品经理的一天是啥样的?
  6. 比尔盖茨,马斯克、霍金都告诉你:为什么要警惕人工智能(中)
  7. 解体症状---被封印的灵魂
  8. H5 六边形消除游戏开发
  9. Mac下打开多个eclipse
  10. Cookie, LocalStorage 与 SessionStorage异同