You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snowflake中能否用递归CTE将父子层级表展平为宽表?

Snowflake递归CTE实现父子层级展平问题

问题背景

我需要将Snowflake中的父子层级表展平,现有多临时表的冗余方案可实现需求,但希望用递归CTE写出更易读、高效的代码,尝试后得到的结果不符合预期。

源表结构(parentmember_table)

MemberIdParentMemberIdMemberLevel
111
612
100740763
101055110074074

目标展平表(flat_table)

Level1Level2Level3Level4
1610074071010551

现有冗余实现方案

use database MY_DATABASE;

create temporary table parentmember_table (memberid integer, parentmemberid integer, memberlevel integer);

INSERT INTO parentchild VALUES
  (1,       1,       1), -- root is where memberid = parentmemberid
  (6,       1,       2),
  (1007407, 6,       3),
  (1010551, 1007407, 4)
;


create or replace temporary table t0 as
select  parentmemberid as Level1
        , null as Level2
        , null as Level3
        , null as Level4
        , memberid
        , memberlevel
from    parentchild
where   parentmemberid = memberid
;


create or replace temporary table t1 as
select  a.Level1
        , case  when (b.memberlevel = 2) then b.memberid
                else coalesce(a.Level2, null)
                end as Level2
        
        , case  when (b.memberlevel = 3) then b.memberid
                else coalesce(a.Level3, null)
                end as Level3
        
        , case  when (b.memberlevel = 4) then b.memberid
                else coalesce(a.Level4, null)
                end as Level4
        
        , b.memberid as memberid
        , b.memberlevel as memberlevel
from    t0 as a
        , parentchild as b
where   b.parentmemberid = a.memberid
        and b.parentmemberid <> b.memberid
;


create or replace temporary table t2 as
select  a.Level1
        , case  when (b.memberlevel = 2) then b.memberid
                else coalesce(a.Level2, null)
                end as Level2
        
        , case  when (b.memberlevel = 3) then b.memberid
                else coalesce(a.Level3, null)
                end as Level3
        
        , case  when (b.memberlevel = 4) then b.memberid
                else coalesce(a.Level4, null)
                end as Level4
        
        , b.memberid as memberid
        , b.memberlevel as memberlevel
from    t1 as a
        , parentchild as b
where   b.parentmemberid = a.memberid
        and b.parentmemberid <> b.memberid
;

create or replace temporary table flat_table as
select  a.Level1
        , case  when (b.memberlevel = 2) then b.memberid
                else coalesce(a.Level2, null)
                end as Level2
        
        , case  when (b.memberlevel = 3) then b.memberid
                else coalesce(a.Level3, null)
                end as Level3
        
        , case  when (b.memberlevel = 4) then b.memberid
                else coalesce(a.Level4, null)
                end as Level4
        
        , b.memberid as memberid
        , b.memberlevel as memberlevel
from    t2 as a
        , parentchild as b
where   b.parentmemberid = a.memberid
        and b.parentmemberid <> b.memberid
;

递归CTE尝试及错误结果

递归CTE代码

create or replace temporary table recursive_cte_table as (
WITH RECURSIVE t (
        Level1
        , Level2
        , Level3
        , Level4
        , MemberId
        , MemberLevel
        ) AS (

        -- anchor_clause
        select  MemberId as Level1
                , null as Level2
                , null as Level3
                , null as Level4
                , MemberId
                , MemberLevel
        from    parentchild
        where   ParentMemberID = MemberID

        UNION ALL

        -- recursive_clause
        select  a.Level1
                , case  when (b.MemberLevel = 2) then b.MemberId
                        end as Level2
                , case  when (b.MemberLevel = 3) then b.MemberId
                        end as Level3
                , case  when (b.MemberLevel = 4) then b.MemberId
                        end as Level4
                , b.MemberId as MemberId
                , b.MemberLevel as MemberLevel
        from    t as a
                , parentchild as b
        where   b.ParentMemberId = a.MemberId
                and b.ParentMemberId <> b.MemberId
)

SELECT * FROM t
);

得到的错误结果

Level1Level2Level3Level4MemberIdMemberLevel
1nullnullnull11
16nullnull62
1null1007407null10074073
1nullnull101055110105514

提问

请问是我的递归CTE代码存在错误,还是对递归CTE的适用场景理解有误?

内容的提问来源于stack exchange,提问作者Ali Mustafa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:49:56