Lag和Lead分析函数可以在同一次查询中取出同一字段的前N行的数据(Lag)和后N行的数据(Lead)作为独立的列。
在实际应用当中,若要用到取今天和昨天的某字段差值时,Lag和Lead函数的应用就显得尤为重要。当然,这种操作可以用表的自连接实现,但是LAG和LEAD与left join、rightjoin等自连接相比,效率更高,SQL更简洁。下面我就对这两个函数做一个简单的介绍。
函数语法如下:
lag(exp_str,offset,defval) over(partion by ..order by …)
lead(exp_str,offset,defval) over(partion by ..order by …)
其中exp_str是字段名
Offset是偏移量,即是上1个或上N个的值,假设当前行在表中排在第5行,则offset 为3,则表示我们所要找的数据行就是表中的第2行(即5-3=2)。
Defval默认值,当两个函数取上N/下N个值,当在表中从当前行位置向前数N行已经超出了表的范围时,lag()函数将defval这个参数值作为函数的返回值,若没有指定默认值,则返回NULL,那么在数学运算中,总要给一个默认值才不会出错。
first-简单实现
先创建一个数据
SET TBLPROPERTIES ('transactional'='true');
CREATE TABLE IF NOT EXISTS lag_lead(
id BIGINT
,province STRING
,mounth STRING
,gdp INT
)
COMMENT "lag_lead";
--select * from lag_lead ;
insert into lag_lead
values (1,'浙江省','1月',10),
(2,'浙江省','2月',12),
(3,'浙江省','3月',15),
(4,'浙江省','4月',18),
(5,'浙江省','5月',20);
数据如下
id | province | mounth | gdp |
---|---|---|---|
1 | 浙江省 | 1月 | 10 |
2 | 浙江省 | 2月 | 12 |
3 | 浙江省 | 3月 | 15 |
4 | 浙江省 | 4月 | 18 |
5 | 浙江省 | 5月 | 20 |
-- LAG
SELECT id,province,mounth,gdp,LAG(gdp)OVER(ORDER BY mounth) as last_dgp
FROM lag_lead
;
-- lead
SELECT id,province,mounth,gdp,lead(gdp)OVER(ORDER BY mounth) as next_dgp
FROM lag_lead
;
结果如下:
lag
id | province | mounth | gdp | last_dgp |
---|---|---|---|---|
1 | 浙江省 | 1月 | 10 | \N |
2 | 浙江省 | 2月 | 12 | 10 |
3 | 浙江省 | 3月 | 15 | 12 |
4 | 浙江省 | 4月 | 18 | 15 |
5 | 浙江省 | 5月 | 20 | 18 |
lead
id | province | mounth | gdp | next_dgp |
---|---|---|---|---|
1 | 浙江省 | 1月 | 10 | 12 |
2 | 浙江省 | 2月 | 12 | 15 |
3 | 浙江省 | 3月 | 15 | 18 |
4 | 浙江省 | 4月 | 18 | 20 |
5 | 浙江省 | 5月 | 20 | \N |
second–分区
按照省份分区
insert into lag_lead
values (6,'山东省','1月',8),
(7,'山东省','2月',12),
(8,'山东省','3月',13),
(9,'山东省','4月',17),
(10,'山东省','5月',20);
SELECT id,province,mounth,gdp,LAG(gdp)OVER(PARTITION BY province ORDER BY mounth) as last_dgp,lead(gdp)OVER(PARTITION BY province ORDER BY mounth) as next_dgp
FROM lag_lead
ORDER BY id ASC
;
结果如下