您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

一文详解SQL窗口函数

2025/4/6 3:38:37发布47次查看
本篇文章给大家带来了关于sql的相关知识,其中主要整理了窗口函数的相关问题,sql窗口函数为在线分析处理(olap)和商业智能(bi)提供了复杂分析和报表统计的功能,例如产品的累计销售额统计、分类排名、同比/环比分析等,下面一起来看一下,希望对大家有帮助。
推荐学习:《sql教程》
什么是窗口函数sql窗口函数为在线分析处理(olap)和商业智能(bi)提供了复杂分析和报表统计的功能,例如产品的累计销售额统计、分类排名、同比/环比分析等。这些功能通常很难通过聚合函数和分组操作来实现。
窗口函数(window function)可以像聚合函数一样对一组数据进行分析并返回结果,二者的不同之处在于,窗口函数不是将一组数据汇总成单个结果,而是为每一行数据都返回一个结果。聚合函数和窗口函数的区别如下图所示。
以sum函数为例演示这两种函数的差异,以下语句中的sum()是一个聚合函数:
select sum(salary) as 所有员工月薪总和from employee
以上sum函数可作为聚合函数使用,表示将所有员工的数据汇总成一个结果。因此,查询返回了所有员工的月薪总和:
以下语句中的sum()是一个窗口函数:
select emp_name as 员工姓名,       sum(salary) over () as 所有员工月薪总和from employee;
其中,关键字over表明sum()是一个窗口函数。括号内为空,表示将所有数据作为一个分组进行汇总。该查询返回的结果如下:
以上查询结果返回了所有的员工姓名,并且通过聚合函数sum()为每个员工都返回了相同的汇总结果。
从以上示例中可以看出,窗口函数的语法与聚合函数的不同之处在于,它包含了一个over子句。over子句用于指定一个数据分析的窗口,完整的窗口函数定义如下:
其中window_function是窗口函数的名称,expression是可选的分析对象(字段名或者表达式),over子句包含分区(partition by)、排序(order by)以及窗口大小(frame_clause)3个选项。
提示:聚合函数将同一个分组内的多行数据汇总成单个结果,窗口函数则保留了所有的原始数据。在某些数据库中,窗口函数也被称为在线分析处理(olap)函数,或者分析函数(analytic function)。
窗口函数组成部分1.创建数据分区窗口函数over子句中的partition by选项用于定义分区,其作用类似于查询语句中的group by子句。如果我们指定了分区选项,窗口函数将会分别针对每个分区单独进行分析。
例如,以下语句按照不同部门分别统计员工的月薪合计:
select emp_name as 员工姓名, salary 月薪, dept_id as 部门编号,       sum(salary) over (         partition by dept_id       ) as 部门合计from employee;
其中,partition by选项表示按照部门进行分区。查询返回的结果如下:
查询结果中的前3行数据属于同一个部门,因此它们对应的部门合计字段都等于80000(30000+26000+24000)。其他部门的员工采用同样的方式进行统计。
提示:在窗口函数over子句中指定了partition by选项之后,我们无须使用group by子句也能获得分组统计结果。
如果不指定partition by选项,表示将全部数据作为一个整体进行分析。
2.分区内的排序窗口函数over子句中的order by选项用于指定分区内数据的排序方式,作用类似于查询语句中的order by子句。
排序选项通常用于数据的分类排名。例如,以下语句用于分析员工在部门内的月薪排名:
select emp_name as 员工姓名, salary 月薪, dept_id as 部门编号,       rank() over (         partition by dept_id         order by salary desc       ) as 部门内排名from employee;
其中,rank函数用于计算数据的名次,partition by选项表示按照部门进行分区,order by选项表示在部门内按照月薪从高到低进行排序。查询返回的结果如下:
查询结果中的前3行数据属于同一个部门:“刘备”的月薪最高,在部门内排名第1;“关羽”排名第2;“张飞”排名第3。其他部门的员工采用同样的方式进行排名。
提示:窗口函数over子句中的order by选项和查询语句中的order by子句的使用方法相同。因此,也可以使用nulls first或者nulls last选项指定空值的排序位置。
3.指定窗口大小窗口函数over子句中的frame_clause选项用于指定一个移动的分析窗口,窗口总是位于分区的范围之内,是分区的一个子集。在指定了分析窗口之后,窗口函数不再基于分区进行分析,而是基于窗口内的数据进行分析。
窗口选项可以用于实现各种复杂的分析功能,例如计算累计到当前日期为止的销售额总和,每个月及其前后各n个月的平均销售额等。
指定窗口大小的具体选项如下:
其中,rows表示以数据行为单位计算窗口的偏移量,range表示以数值(例如10天、5km等)为单位计算窗口的偏移量。
frame_start选项用于定义窗口的起始位置,可以指定以下内容之一:
●unbounded preceding——表示窗口从分区的第一行开始。
●n preceding——表示窗口从当前行之前的第n行开始。
●current row——表示窗口从当前行开始。
frame_end选项用于定义窗口的结束位置,可以指定以下内容之一:
●current row——表示窗口到当前行结束。
●m following——表示窗口到当前行之后的第m行结束。
●unbounded following——表示窗口到分区的最后一行结束。
下图说明了这些窗口大小选项的含义
下面语句表示分析窗口从当前分区的第一行开始,直到当前行结束,即对应到图中前面5行记录。
rows between unbounded preceding and current row
窗口函数分类1.聚合窗口函数许多常见的聚合函数也可以作为窗口函数使用,包括avg()、sum()、count()、max()以及min()等函数。
sql窗口函数-聚合窗口函数
2.排名窗口函数排名窗口函数用于对数据进行分组排名,包括row_number()、rank()、dense_rank()、percent_rank()、cume_dist()以及ntile()等函数。
sql窗口函数-排名窗口函数
3.取值窗口函数取值窗口函数用于返回指定位置上的数据行,包括first_value()、last_value()、lag()、lead()、nth_value()等函数。
sql窗口函数-取值窗口函数
示例表和脚本--员工信息表create table employee    ( emp_id    number    , emp_name  varchar2(50) not null    , sex       varchar2(10) not null    , dept_id   integer not null    , manager   integer    , hire_date date not null    , job_id    integer not null    , salary    numeric(8,2) not null    , bonus     numeric(8,2)    , email     varchar2(100) not null  , comments  varchar2(500)  , create_by varchar2(50) not null  , create_ts timestamp not null  , update_by varchar2(50)   , update_ts timestamp    ) ;comment on table employee is '员工信息表';comment on column employee.emp_id is '员工编号,自增主键';comment on column employee.emp_name is '员工姓名';comment on column employee.sex is '性别';comment on column employee.dept_id is '部门编号';comment on column employee.manager is '上级经理';comment on column employee.hire_date is '入职日期';comment on column employee.job_id is '职位编号';comment on column employee.salary is '月薪';comment on column employee.bonus is '年终奖金';comment on column employee.email is '电子邮箱';comment on column employee.comments is '备注信息';comment on column employee.create_by is '创建者';comment on column employee.create_ts is '创建时间';comment on column employee.update_by is '修改者';comment on column employee.update_ts is '修改时间';  insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (1,'刘备', '男', 1, null, date '2000-01-01', 1, 30000, 10000, 'liubei@shuguo.com', null, 'admin', timestamp '2000-01-01 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (2,'关羽', '男', 1, 1, date '2000-01-01', 2, 26000, 10000, 'guanyu@shuguo.com', null, 'admin', timestamp '2000-01-01 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (3,'张飞', '男', 1, 1, date '2000-01-01', 2, 24000, 10000, 'zhangfei@shuguo.com', null, 'admin', timestamp '2000-01-01 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (4,'诸葛亮', '男', 2, 1, date '2006-03-15', 3, 24000, 8000, 'zhugeliang@shuguo.com', null, 'admin', timestamp '2006-03-15 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (5,'黄忠', '男', 2, 4, date '2008-10-25', 4, 8000, null, 'huangzhong@shuguo.com', null, 'admin', timestamp '2008-10-25 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (6,'魏延', '男', 2, 4, date '2007-04-01', 4, 7500, null, 'weiyan@shuguo.com', null, 'admin', timestamp '2007-04-01 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (7,'孙尚香', '女', 3, 1, date '2002-08-08', 5, 12000, 5000, 'sunshangxiang@shuguo.com', null, 'admin', timestamp '2002-08-08 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (8,'孙丫鬟', '女', 3, 7, date '2002-08-08', 6, 6000, null, 'sunyahuan@shuguo.com', null, 'admin', timestamp '2002-08-08 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (9,'赵云', '男', 4, 1, date '2005-12-19', 7, 15000, 6000, 'zhaoyun@shuguo.com', null, 'admin', timestamp '2005-12-19 10:00:00', 'admin', timestamp '2006-12-31 10:00:00');insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (10,'廖化', '男', 4, 9, date '2009-02-17', 8, 6500, null, 'liaohua@shuguo.com', null, 'admin', timestamp '2009-02-17 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (11,'关平', '男', 4, 9, date '2011-07-24', 8, 6800, null, 'guanping@shuguo.com', null, 'admin', timestamp '2011-07-24 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (12,'赵氏', '女', 4, 9, date '2011-11-10', 8, 6600, null, 'zhaoshi@shuguo.com', null, 'admin', timestamp '2011-11-10 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (13,'关兴', '男', 4, 9, date '2011-07-30', 8, 7000, null, 'guanxing@shuguo.com', null, 'admin', timestamp '2011-07-30 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (14,'张苞', '男', 4, 9, date '2012-05-31', 8, 6500, null, 'zhangbao@shuguo.com', null, 'admin', timestamp '2012-05-31 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (15,'赵统', '男', 4, 9, date '2012-05-03', 8, 6000, null, 'zhaotong@shuguo.com', null, 'admin', timestamp '2012-05-03 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (16,'周仓', '男', 4, 9, date '2010-02-20', 8, 8000, null, 'zhoucang@shuguo.com', null, 'admin', timestamp '2010-02-20 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (17,'马岱', '男', 4, 9, date '2014-09-16', 8, 5800, null, 'madai@shuguo.com', null, 'admin', timestamp '2014-09-16 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (18,'法正', '男', 5, 2, date '2017-04-09', 9, 10000, 5000, 'fazheng@shuguo.com', null, 'admin', timestamp '2017-04-09 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (19,'庞统', '男', 5, 18, date '2017-06-06', 10, 4100, 2000, 'pangtong@shuguo.com', null, 'admin', timestamp '2017-06-06 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (20,'蒋琬', '男', 5, 18, date '2018-01-28', 10, 4000, 1500, 'jiangwan@shuguo.com', null, 'admin', timestamp '2018-01-28 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (21,'黄权', '男', 5, 18, date '2018-03-14', 10, 4200, null, 'huangquan@shuguo.com', null, 'admin', timestamp '2018-03-14 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (22,'糜竺', '男', 5, 18, date '2018-03-27', 10, 4300, null, 'mizhu@shuguo.com', null, 'admin', timestamp '2018-03-27 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (23,'邓芝', '男', 5, 18, date '2018-11-11', 10, 4000, null, 'dengzhi@shuguo.com', null, 'admin', timestamp '2018-11-11 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (24,'简雍', '男', 5, 18, date '2019-05-11', 10, 4800, null, 'jianyong@shuguo.com', null, 'admin', timestamp '2019-05-11 10:00:00', null, null);insert into employee(emp_id,emp_name, sex, dept_id, manager, hire_date, job_id, salary, bonus, email, comments, create_by, create_ts, update_by, update_ts) values (25,'孙乾', '男', 5, 18, date '2018-10-09', 10, 4700, null, 'sunqian@shuguo.com', null, 'admin', timestamp '2018-10-09 10:00:00', null, null);
推荐学习:《sql教程》
以上就是一文详解sql窗口函数的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product