【和SQL对比】对分组子集做跨行运算
找出发生过连续三交易日涨停(涨幅>=10%)的股票
SQL解法
with A as (select 代码,交易日, 收盘价/lag(收盘价) over(partition by 股票 order by 交易日)-1 涨幅 from 股价表), B as (select 代码, case when 涨幅>=0.1 and lag(涨幅) over(partition by 代码 order by 交易日)>=0.1 and lag(涨幅,2) over(partition by 代码 order by 交易日)>=0.1 then 1 else 0 end 三天连涨标志 from A) select distinct 代码 from B where 三天连涨标志=1
窗口函数可以计算出涨幅,再对涨幅施用窗口函数可计算出三天连涨标志,经过多层嵌套后终于可以计算出结果,多了一层分组导致复杂度陡增,还好有with把嵌套SQL写成分步计算的样子。
SPL解法
A | B | C | D | |
1 | =demo.query(“select * from 股价表”).group(代码).(~.sort(交易日期)) | =[] | 结果集在C1 | |
2 | for A1 | =0 | ||
3 | if A2.pselect(B2=if(close_price/close_price[-1]>=1.1,B2+1,0):3)>0 | 有三天涨停 | ||
4 | >C1=C1|A2.代码 |
或用子计算语句
A | B | |
1 | =股价表.group(代码).(~.sort(交易日期)) | |
2 | ==A1.select(?) | =0 |
3 | =~.pselect(B2=if(收盘价/收盘价[-1]>=1.1,B2+1,0):3)>0 | |
4 | =A2.(代码) |
天然可分步计算的SPL在多一层分组时复杂度增加有限,使用子计算语句或循环将外层剥开,内层计算就如同平时层数少的情况一样,不会带来思维上的困难。
这段代码很容易扩展成寻找有n天连续涨停,而且找到第一个连续涨停日就停止计算剩下的涨幅,相比之下,SQL的写法则很难扩展,同时窗口函数还要求必须把所有跨行计算全部算完后才能过滤。