While 循环插入到 CTE 的表格中 (Snowflake)

While loop insert into table with CTE's (Snowflake)

提问人:Kholz 提问时间:7/29/2023 最后编辑:Simeon PilgrimKholz 更新时间:7/29/2023 访问量:145

问:

以下内容的正确 Snowflake 语法:

execute immediate $$ 
declare
  end_period int default 10;
  start_period int default 0;
 
begin 
  while ($start_period < $end_period ) do  

    with cte_example as (
       select 
          account_id, 
          sum(sales) as sales
       from table
       where period <= $end_period 
       group by account_id
    )
    insert into target_table (account_id, sales)
    select account_id, sales
    from cte_example

    end_period := end_period  + 1;
  end while;
end;
$$ 

我想在 Snowflake 中做一个 while 循环,每次迭代都插入到表中

sql 循环 while-loop 语法 snowflake-cloud-data-platform

评论

0赞 NickW 7/29/2023
您的意思是在您的 DECLARE 部分中current_period而不是end_period吗?
0赞 Kholz 7/29/2023
修复为仅使用start_period和end_period
1赞 NickW 7/29/2023
好的 - 那么现在的实际问题是什么?例如,你的代码是否出错(错误是什么),它是否没有给出你想要的结果(它做了什么),还是什么?
0赞 Simeon Pilgrim 7/29/2023
此外,循环在数据库中通常是“坏的”,几乎任何可以在循环中实现的东西(除了递归)都可以在关系代数中完成,你最好将任务换成这种思维方式。
0赞 Kholz 7/29/2023
当前错误是意外的“as”,紧跟在“with cte_example”之后

答:

0赞 Simeon Pilgrim 7/29/2023 #1

现在我重新格式化了 SQL 以读取它的作用,您应该使用生成器来形成行,并使用 a 为您提供行号,然后您可以将其用作 WHERE 子句(再次通过连接),然后一旦您拥有正确的行集,只需在一次操作中插入这些行。您需要在连接后按 rn 编号进行分组,以便小计正确。10-0 = 10row_number() over (order by null) -1

所以第一部分是:

with fake_sales(account_id, period, sales) as (
    select * from values
        (100,  1, 11),
        (100,  2, 12),
        (100,  3, 13)
), gens as (
    select row_number() over(order by null) as rn
    from table(generator(rowcount=>10))
)
select *
from gens as g
join fake_sales as s
    on s.period <= g.rn

enter image description here

现在汇总:

with fake_sales(account_id, period, sales) as (
    select * from values
        (100,  1, 11),
        (100,  2, 12),
        (100,  3, 13)
), gens as (
    select row_number() over(order by null) as rn
    from table(generator(rowcount=>10))
)
select account_id, 
    sum(sales) as sales
from gens as g
join fake_sales as s
    on s.period <= g.rn
group by s.account_id, g.rn
order by 1

enter image description here

您的 SQL 的问题是这是 WITH 绑定到 SELECT 而不是 INSERT,因此您想要:

insert into target_table (account_id, sales)
    with cte_example as (
       select 
          account_id, 
          sum(sales) as sales
       from table
       where period <= $end_period 
       group by account_id
    )
    select account_id, sales
    from cte_example

评论

0赞 Kholz 7/29/2023
谢谢你的例子。似乎是一个很酷的潜在解决方案。我得在星期一试一试。
0赞 Simeon Pilgrim 7/29/2023
你这段代码正在做,是一步到位的循环步骤。这就是您获得性能的方式。如果你学会了如何以这种方式思考,数据库将变得非常容易跳舞。
0赞 Kholz 7/29/2023
我将不得不跟进这一点,实际的“句点”并不像 0-10 那么容易。它们是 YYYYMM 形式的 periodID。这种情况何时将正确添加迭代这些: case when substring(cast($periodid as varchar),5,2) = 12 then $periodid + 89 else $periodid + 1 end 我将如何在您的代码中实现它?
0赞 Simeon Pilgrim 7/29/2023
您可以将任何您喜欢的逻辑放入 CTE 中,以从值空间 X 到值空间 Y 进行预处理。重点是一次从行更改、转换和查找。要了解什么是大局,需要建立结果,以便它们可以在最有效的庄园中转换大量数据。然后将这些构建的数据连接到最小的结果集上。因为每行处理不能很好地扩展,并且联接成本很高。又名性能锥体从更少。事实上,至少仍然得到预期的结果。