SQL常用窗口函数

SQL运行顺序

SQL常用窗口函数_第1张图片

窗口函数

窗口函数是一种分析型的 OLAP(Online Anallytical Processing,联机分析处理)函数,意思是对数据库数据进行实时分析处理。

语法

select  <窗口函数> over ( partition by <分组列>order by <排序列> ) 

分类

  • 排名函数:row_number(),rank(),dense_rank()
  • 聚合函数:max(),min(),count(),sum(),avg(),median()
  • 向前向后取值:lag(),lead()
  • 百分位:percent_rank()
  • 取值函数:first_value(),last_value(),nth_value()
  • 分箱函数:ntile()

使用说明

1、排名函数
函数 用法
row_number() 同薪不同名,相当于行号,例如3000、2000、2000、1000排名后为1、2、3、4
rank() 同薪同名,有跳级,例如3000、2000、2000、1000排名后为1、2、2、4
dense_rank() 同薪同名,无跳级,例如3000、2000、2000、1000排名后为1、2、2、3
2、聚合函数
函数 用法
max() 最大值
min() 最小值
avg() 平均值
sum() 求和
median() 中位数

示例:

select sales_id, qty,
max(qty) over (order by sales_id rows unbounded preceding) as max_value
from winsales
order by sales_id;
---------------------
sales_id| qty | max
---------+-----+-----
10001 |  10 |  10
10005 |  30 |  30
10006 |  10 |  30
20001 |  20 |  30
20002 |  20 |  30
30001 |  10 |  30
30003 |  15 |  30
30004 |  20 |  30
30007 |  30 |  30
40001 |  40 |  40
40005 |  10 |  40
3、向前向后取值
函数 用法
lag(field,n,default) 前N行,在一次查询中取出当前行的同一字段(field参数)的前面第n行的数据,如果没有用default代替
lead(field,n,default) 后N行,在一次查询中取出当前行的同一字段(field参数)的后面第n行的数据,如果没有用default代替

lag() 示例:
以下示例显示 买家 ID 为 3 的购票时间、购票数。
需求是:将每次购票与上一购票进行比较,返回每次购票的上一购票数。

select buyer_id , buy_time, buynum,
lag(buynum,1) over (order by buyer_id, buy_time) as pre_buynum
from sales 
where buyer_id= 3 
order by buyer_id, buy_time;

--------------------------------------------------------
buyer_id |      buy_time       | buynum | pre_buynum
---------+---------------------+---------+--------------
3 | 2008-01-16 01:06:09 |       1 |
3 | 2008-01-28 02:10:01 |       1 |            1
3 | 2008-03-12 10:39:53 |       1 |            1
3 | 2008-03-13 02:56:07 |       1 |            1
3 | 2008-03-29 08:21:39 |       2 |            1
3 | 2008-04-27 02:39:01 |       1 |            2
3 | 2008-08-16 07:04:37 |       2 |            1
3 | 2008-08-22 11:45:26 |       2 |            2
3 | 2008-09-12 09:11:25 |       1 |            2
3 | 2008-10-01 06:22:37 |       1 |            1
3 | 2008-10-20 01:55:51 |       2 |            1
3 | 2008-10-28 01:30:40 |       1 |            2

lead() 示例:
以下示例提供了 SALES 表中于 2008 年 1 月 1 日与 1 月 2 日已售票的事件的佣金以及为后续销售中售票所付的佣金。

select eventid, commission, saletime,
lead(commission, 1) over (order by saletime) as next_comm
from sales 
where saletime between '2008-01-01 00:00:00' and '2008-01-02 12:59:59'
order by saletime;

--------------------------------------------------------
eventid | commission |      saletime       | next_comm
---------+------------+---------------------+-----------
6213 |      52.05 | 2008-01-01 01:00:19 |    106.20
7003 |     106.20 | 2008-01-01 02:30:52 |    103.20
8762 |     103.20 | 2008-01-01 03:50:02 |     70.80
1150 |      70.80 | 2008-01-01 06:06:57 |     50.55
1749 |      50.55 | 2008-01-01 07:05:02 |    125.40
8649 |     125.40 | 2008-01-01 07:26:20 |     35.10
2903 |      35.10 | 2008-01-01 09:41:06 |    259.50
6605 |     259.50 | 2008-01-01 12:50:55 |    628.80
6870 |     628.80 | 2008-01-01 12:59:34 |     74.10
6977 |      74.10 | 2008-01-02 01:11:16 |     13.50
4650 |      13.50 | 2008-01-02 01:40:59 |     26.55
4515 |      26.55 | 2008-01-02 01:52:35 |     22.80
5465 |      22.80 | 2008-01-02 02:28:01 |     45.60
5465 |      45.60 | 2008-01-02 02:28:02 |     53.10
7003 |      53.10 | 2008-01-02 02:31:12 |     70.35
4124 |      70.35 | 2008-01-02 03:12:50 |     36.15
1673 |      36.15 | 2008-01-02 03:15:00 |   1300.80
...

4、百分位
函数 用法
percent_rank() 计算分组内每一行所在的百分比排名

以下示例计算每个卖家的销售数量所在的百分比排名:

select sellerid, qty, 
percent_rank() over (partition by sellerid order by qty) 
from winsales;

----------------------------------------
sellerid	qty		percent_rank
----------------------------------------
1		10.00		0.0
1		10.64		0.5
1		30.37		1.0
3		10.04		0.0
3		15.15		0.33
3		20.75		0.67
3		30.55		1.0
2		20.09		0.0
2		20.12		1.0
4		10.12		0.0
4		40.23		1.0

5、取值函数
函数 用法
first_value() 分组内第一行的值
last_value() 分组内最后一行的值
nth_value(expr, n) 分组内第n行的值
6、分箱函数

函数 用法

函数 用法
ntile(n) 将分区中已排序的行划分为大小尽可能相等的n个已排名组(等频分箱)

以下示例将于 2008 年 8 月 26 日购买 Hamlet 门票所付价格划分到四个排名组中。结果集为 17 个行,几乎均匀地划分到排名 1 到 4 中:

select eventname, caldate, pricepaid, 
ntile(4) over(order by pricepaid desc) from sales, event, date
where sales.eventid=event.eventid 
	  and event.dateid=date.dateid 
	  and eventname='Hamlet'
	  and caldate='2008-08-26'
order by 4;
--------------------------------------------
eventname |  caldate   | pricepaid | ntile
-----------+------------+-----------+-------
Hamlet    | 2008-08-26 |   1883.00 |     1
Hamlet    | 2008-08-26 |   1065.00 |     1
Hamlet    | 2008-08-26 |    589.00 |     1
Hamlet    | 2008-08-26 |    530.00 |     1
Hamlet    | 2008-08-26 |    472.00 |     1
Hamlet    | 2008-08-26 |    460.00 |     2
Hamlet    | 2008-08-26 |    355.00 |     2
Hamlet    | 2008-08-26 |    334.00 |     2
Hamlet    | 2008-08-26 |    296.00 |     2
Hamlet    | 2008-08-26 |    230.00 |     3
Hamlet    | 2008-08-26 |    216.00 |     3
Hamlet    | 2008-08-26 |    212.00 |     3
Hamlet    | 2008-08-26 |    106.00 |     3
Hamlet    | 2008-08-26 |    100.00 |     4
Hamlet    | 2008-08-26 |     94.00 |     4
Hamlet    | 2008-08-26 |     53.00 |     4
Hamlet    | 2008-08-26 |     25.00 |     4

7、移动平均
函数 用法
n PRECEDING 前n行
n FOLLOWING 后n行
CURRENT ROW 当前行
UNBOUNDED PRECEDING 窗口第一行
UNBOUNDED FOLLOWING 窗口的最后一行

你可能感兴趣的:(sql,大数据,数据库,窗口函数)