SQL (Snowflake) - 递归引用自身的列
SQL (Snowflake) - Column that recursively refers to itself
我看过很多关于这个主题的帖子,但找不到完全相同的帖子。
我想创建一个包含引用自身的列的视图。在下面的示例中:
- 值 1 + 2 是贯穿整个视图的静态值。
- 值 3 有更新的数据,所以我希望它在值 3 中有数据时执行值 3 +(值 1 - 值 2)。
- 当值3没有数据时,使用它的先验值计算。
Index
Value1
Value2
Value3
Calculation
1
0.5
0.25
1
1.25
2
0.5
0.25
1.5
3
0.5
0.25
1.75
这可能吗?到目前为止,我已经使用 LAG 或递归 CTE 计算索引 = 2 的行,但似乎无法弄清楚如何让它继续计算。
使用稍微扩展的示例数据来显示新的 value3 作为先例:
WITH data(Index, Value1, Value2, Value3) AS (
SELECT * FROM VALUES
(1, 0.5, 0.25, 1),
(2, 0.5, 0.25, null),
(3, 0.5, 0.25, null),
(4, 0.5, 0.25, 10),
(5, 0.5, 0.25, null),
(6, 0.5, 0.25, null),
(7, 0.5, 0.25, null)
)
select d.*
,iff(d.value3 is not null, d.index, null) as idx_k
,lag(d.value3) ignore nulls over(order by d.index) as l_value3
,lag(idx_k) ignore nulls over(order by d.index) as l_idx_k
,d.index - iff(idx_k is not null, idx_k, l_idx_k)+1 as r_d
,iff(d.value3 is not null, d.value3, l_value3) + r_d*(d.value1-d.value2) as calc
from data as d
order by 1;
给出:
INDEX
VALUE1
VALUE2
VALUE3
IDX_K
L_VALUE3
L_IDX_K
R_D
CALC
1
0.5
0.25
1
1
1
1.25
2
0.5
0.25
1
1
2
1.5
3
0.5
0.25
1
1
3
1.75
4
0.5
0.25
10
4
1
1
1
10.25
5
0.5
0.25
10
4
2
10.5
6
0.5
0.25
10
4
3
10.75
7
0.5
0.25
10
4
4
11
可以拼成:
select d.*
,iff(d.value3 is not null, d.value3, lag(d.value3) ignore nulls over(order by d.index)) + (d.index - iff(d.value3 is not null, iff(d.value3 is not null, d.index, null), lag(iff(d.value3 is not null, d.index, null)) ignore nulls over(order by d.index))+1)*(d.value1-d.value2) as calc
from data as d
如果你真的想要,但我更倾向于将其包装在 sub-select 中,只是为了让它呈现得更好:
select index, value1, value2, value3, calc
from (
select d.*
,iff(d.value3 is not null, d.index, null) as idx_k
,lag(d.value3) ignore nulls over(order by d.index) as l_value3
,lag(idx_k) ignore nulls over(order by d.index) as l_idx_k
,d.index - iff(idx_k is not null, idx_k, l_idx_k)+1 as r_d
,iff(d.value3 is not null, d.value3, l_value3) + r_d*(d.value1-d.value2) as calc
from data as d
)
order by 1
递归 CTE:
WITH recursive r_cte as (
select index, value1, value2, value3, value3 as calc
from data
where index = 1
union all
select d.index, d.value1, d.value2, d.value3, iff(d.value3 is null, r.calc, d.value3) + d.value1 - d.value2 as calc
from r_cte as r
join data d on r.index + 1 = d.index
)
select * from r_cte
我看过很多关于这个主题的帖子,但找不到完全相同的帖子。
我想创建一个包含引用自身的列的视图。在下面的示例中:
- 值 1 + 2 是贯穿整个视图的静态值。
- 值 3 有更新的数据,所以我希望它在值 3 中有数据时执行值 3 +(值 1 - 值 2)。
- 当值3没有数据时,使用它的先验值计算。
Index | Value1 | Value2 | Value3 | Calculation |
---|---|---|---|---|
1 | 0.5 | 0.25 | 1 | 1.25 |
2 | 0.5 | 0.25 | 1.5 | |
3 | 0.5 | 0.25 | 1.75 |
这可能吗?到目前为止,我已经使用 LAG 或递归 CTE 计算索引 = 2 的行,但似乎无法弄清楚如何让它继续计算。
使用稍微扩展的示例数据来显示新的 value3 作为先例:
WITH data(Index, Value1, Value2, Value3) AS (
SELECT * FROM VALUES
(1, 0.5, 0.25, 1),
(2, 0.5, 0.25, null),
(3, 0.5, 0.25, null),
(4, 0.5, 0.25, 10),
(5, 0.5, 0.25, null),
(6, 0.5, 0.25, null),
(7, 0.5, 0.25, null)
)
select d.*
,iff(d.value3 is not null, d.index, null) as idx_k
,lag(d.value3) ignore nulls over(order by d.index) as l_value3
,lag(idx_k) ignore nulls over(order by d.index) as l_idx_k
,d.index - iff(idx_k is not null, idx_k, l_idx_k)+1 as r_d
,iff(d.value3 is not null, d.value3, l_value3) + r_d*(d.value1-d.value2) as calc
from data as d
order by 1;
给出:
INDEX | VALUE1 | VALUE2 | VALUE3 | IDX_K | L_VALUE3 | L_IDX_K | R_D | CALC |
---|---|---|---|---|---|---|---|---|
1 | 0.5 | 0.25 | 1 | 1 | 1 | 1.25 | ||
2 | 0.5 | 0.25 | 1 | 1 | 2 | 1.5 | ||
3 | 0.5 | 0.25 | 1 | 1 | 3 | 1.75 | ||
4 | 0.5 | 0.25 | 10 | 4 | 1 | 1 | 1 | 10.25 |
5 | 0.5 | 0.25 | 10 | 4 | 2 | 10.5 | ||
6 | 0.5 | 0.25 | 10 | 4 | 3 | 10.75 | ||
7 | 0.5 | 0.25 | 10 | 4 | 4 | 11 |
可以拼成:
select d.*
,iff(d.value3 is not null, d.value3, lag(d.value3) ignore nulls over(order by d.index)) + (d.index - iff(d.value3 is not null, iff(d.value3 is not null, d.index, null), lag(iff(d.value3 is not null, d.index, null)) ignore nulls over(order by d.index))+1)*(d.value1-d.value2) as calc
from data as d
如果你真的想要,但我更倾向于将其包装在 sub-select 中,只是为了让它呈现得更好:
select index, value1, value2, value3, calc
from (
select d.*
,iff(d.value3 is not null, d.index, null) as idx_k
,lag(d.value3) ignore nulls over(order by d.index) as l_value3
,lag(idx_k) ignore nulls over(order by d.index) as l_idx_k
,d.index - iff(idx_k is not null, idx_k, l_idx_k)+1 as r_d
,iff(d.value3 is not null, d.value3, l_value3) + r_d*(d.value1-d.value2) as calc
from data as d
)
order by 1
递归 CTE:
WITH recursive r_cte as (
select index, value1, value2, value3, value3 as calc
from data
where index = 1
union all
select d.index, d.value1, d.value2, d.value3, iff(d.value3 is null, r.calc, d.value3) + d.value1 - d.value2 as calc
from r_cte as r
join data d on r.index + 1 = d.index
)
select * from r_cte