题目描述:
分数表(game)有字段:球队(team)、球员号码(no)、球员姓名(name)、得分分数(score)、得分时间(time)的一张总表
问题:找出使各种球队反超的球员姓名和的得分时间
题目来源:拼多多面试题:累计求和问题如何分析? (qq.com)
分析:
1、欲知球队反超,则先有两队的得分累计
2、球队反超有两种情况:
1)上一回合,A队领先,该回合B队领先,或者反之;
2)上一回合平分,上上一回合A队领先,该回合B队领先,或者反之。
问题拆解:
1、求出各时刻两支球队的累计得分 <-- 增加新列,为各时刻A队得分、B队得分
#增加各时刻两队得分
select * ,
(case
when team='A' then score else 0 end) as A_score,
(case
when team='B' then score else 0 end) as B_score
from game
order by time
#增加各时刻两队累计得分(此处通过开窗实现累计求和)
select * ,
sum(A_score) over(order by time) as A_sum,
sum(B_score) over(order by time) as B_sum
from
(select * ,
(case
when team='A' then score else 0 end) as A_score,
(case
when team='B' then score else 0 end) as B_score
from game
order by time ) as t
2、求出每回合的领先者,此处可用差值来代替(A_sum - B_sum)--> 求出上一回合、上上一回合的领先者
select * ,
A_sum-B_sum as win,
lag(A_sum - B_sum,1) over (order by time) as win_1,
lag(A_sum - B_sum,2) over (order by time) as win_2
from
(select * ,
sum(A_score) over(order by time) as A_sum,
sum(B_score) over(order by time) as B_sum
from
(select * ,
(case
when team='A' then score else 0 end) as A_score,
(case
when team='B' then score else 0 end) as B_score
from game
order by time ) as t) as t1
3、求出实现反超的时刻和球员姓名
select name, time
from
(select * ,
A_sum-B_sum as win,
lag(A_sum - B_sum,1) over (order by time) as win_1,
lag(A_sum - B_sum,2) over (order by time) as win_2
from
(select * ,
sum(A_score) over(order by time) as A_sum,
sum(B_score) over(order by time) as B_sum
from
(select * ,
(case
when team='A' then score else 0 end) as A_score,
(case
when team='B' then score else 0 end) as B_score
from game
order by time ) as t) as t1) as t2
where (win*win_1 < 0) or (win_1=0 and win*win_2 < 0)
补充:
lag 函数及 lead函数使用规范:
lag(exp_str,offset,default)
lead(exp_str,offset,default)
1、lag代表数据向下偏移,lead代表数据向上偏移
2、exp_str代表字段(对象列)、offset代表偏移量、default代表上/下偏移n个的数据超出范围时填入的值,若不填则为null
参考blog:ORALCE函数:LAG()和LEAD() 分析函数详解_CoderLover-CSDN博客_lag函数