SQL运行顺序
窗口函数
窗口函数是一种分析型的 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 | 窗口的最后一行 |