从 SQL 到 SPL:根据连续值生成计算列
某库表的字段 n 用于排序,x 字段是整数,有时会出现连续的 0。
n | x |
1 | 0 |
2 | 1 |
3 | 2 |
4 | 3 |
5 | 4 |
6 | 2 |
7 | 1 |
8 | 0 |
9 | 1 |
10 | 0 |
11 | 0 |
12 | 0 |
13 | 0 |
14 | 1 |
15 | 2 |
16 | 3 |
17 | 4 |
现在要新增计算列 def,要求是:def 初值为 0;如果当前行 x > 2,则 将 def 置为 1;遇到 3 个连续的 x=0 时,将当前 def 重置为 0;其他情况保持 def 与上一行相同。
n | x | def |
1 | 0 | 0 |
2 | 1 | 0 |
3 | 2 | 0 |
4 | 3 | 1 |
5 | 4 | 1 |
6 | 2 | 1 |
7 | 1 | 1 |
8 | 0 | 1 |
9 | 1 | 1 |
10 | 0 | 1 |
11 | 0 | 1 |
12 | 0 | 0 |
13 | 0 | 0 |
14 | 1 | 0 |
15 | 2 | 0 |
16 | 3 | 1 |
17 | 4 | 1 |
SQL:
with cte as (
select *
,(x > 2) exceeded_2
,(0 = all(array[ x
,lag(x,1,0)over w1
,lag(x,2,0)over w1
]
)
) as should_switch
from have
window w1 as (order by n) )
,cte2 as (
select *,sum(should_switch::int)over(order by n) def_on_period
from cte
)
select n,x,(bool_or(exceeded_2) over w2)::int as def
from cte2
window w2 as (partition by def_on_period
order by n);
SQL要用多个窗口函数 + 多个子查询实现相对位置计算,代码复杂难懂。SPL 提供了表达相对位置的语法: https://try.esproc.com/splx?4OY
A | |
1 | $select n, x, null as def from have.txt order by n |
2 | =A1.run(def=if( x>2:1, x[-2]+x[-1]+x==0:0; def[-1] )) |
A1:加载数据,新增空的计算列。
A2:修改计算列,如果当前行 x>2,则 def 置为 1;如果连续 3 行都是 0,则 def 置为 0;否则 def 保持不变(置为上一行的 def)。[-1] 表示上一行。
英文版 https://c.esproc.com/article/1742201005229