在 Snowflake 中合并 - 不匹配、更新和插入

Merge in Snowflake- Not matched ,Update and Insert

我有两个 table 如下。

来源table:

ID EventDate Updated_at metre Active_flag
1004 2022-03-10 2022-03-15 13 Y
1005 2022-03-18 2022-03-18 50 Y
1006 2022-03-15 2022-03-15 10 Y
1007 2022-03-20 2022-03-20 1 Y

目标table:

ID EventDate Updated_at metre Active_flag
1001 2022-01-01 2022-01-01 10 Y
1002 2022-01-02 2022-01-02 15 Y
1003 2022-03-01 2022-03-01 20 Y
1004 2022-03-10 2022-03-10 10 N
1004 2022-03-10 2022-03-15 13 Y
1005 2022-03-18 2022-03-18 5 Y

我需要对日期 >='2022-03-01' 的目标 table 进行更新和插入(而不是删除)。比较应该是根据ID和Updated_at。这些字段来自 API.

案例一: 当记录不在源中时,我需要在目标 Table 中更新 Active_flag。在此示例中,ID= 1003(因为其他记录不符合日期范围过滤器)应更新为 Active_flage='N'。 ID=1004 和 Updated_as=2022-03-10 不匹配,在目标 table 中应该有 Active_flag='N'(已经有)。

案例二: 如果它们匹配 ID 和 Updated_at,我可以保持原样。(如 ID=1004 和 updated_at=2022-03-15 或 ID=1005 和 Updatyed_at=2022-03 -18).

案例三: 如果它们不匹配并且 ID 不在 Target 中,我希望记录被插入。 喜欢 ID=1006 和 ID=1007.

合并后所需的目标 table 应该是:

ID EventDate Updated_at metre Active_flag
1001 2022-01-01 2022-01-01 10 Y
1002 2022-01-02 2022-01-02 15 Y
1003 2022-03-01 2022-03-01 20 N
1004 2022-03-10 2022-03-10 10 N
1004 2022-03-10 2022-03-15 13 Y
1005 2022-03-15 2022-03-15 5 Y
1006 2022-03-15 2022-03-15 10 Y
1007 2022-03-20 2022-03-20 1 Y

我的问题: 我可以通过在 Snowflake 中使用左连接和右连接并使用两个不同的任务来实现这一点,但我只是想知道我是否可以通过在一个任务中使用 Snowflake 中的 MERGE 来实现这一点?

我试过这个:

    merge into "TEST"."PUBLIC"."Target" T
using (
    SELECT b."ID",b."Updated_at",
    iff(a."ID" is null, 'NOT_MATCHED_BY_SOURCE', 'MATCHED_BY_SOURCE') SOURCE_MATCH,
    iff(b."ID" is null, 'NOT_MATCHED_BY_TARGET', 'MATCHED_BY_TARGET') TARGET_MATCH
    from  "TEST"."PUBLIC"."Source" a
    full join "TEST"."PUBLIC"."Target" b
    on a."ID" = b."ID" and a."Updated_at" = b."Updated_at") S
on S."ID" = T."ID" and S."Updated_at"= T."Updated_at"

WHEN matched  and S.SOURCE_MATCH = 'NOT_MATCHED_BY_SOURCE' and T."EventDate">='2022-03-01' then
    UPDATE SET T."Active_flag" = 'N'
WHEN not matched and S.TARGET_MATCH='NOT_MATCHED_BY_TARGET' THEN
    INSERT (T."ID",T."EventDate",T."Updated_at",T."metre",T."Active_flag") Values (a."ID",a."EventDate",a."Updated_at",a."metre",a."Active_flag")
;

更新部分按预期工作正常,但我在代码的插入部分出现错误,如下所示: SQL 编译错误:错误第 14 行在位置 85 无效标识符 'A.ID'

预先感谢您的指导和帮助。

数据设置:

CREATE table src_table(d int, date date, updated_at date, metre int, active_flag boolean);
CREATE table trg_table(d int, date date, updated_at date, metre int, active_flag boolean);

INSERT into src_table values 
(1004, '2022-03-10','2022-03-15', 13, true),
(1005,  '2022-03-18','2022-03-18', 50, true),
(1006,  '2022-03-15','2022-03-15', 10, true),
(1007,  '2022-03-20','2022-03-20', 1, true);

INSERT into trg_table values 
(1001,'2022-01-01','2022-01-01',10 ,true ),
(1002,'2022-01-02','2022-01-02',15 ,true ),
(1003,'2022-03-01','2022-03-01',20 ,true ),
(1004,'2022-03-10','2022-03-10',10 ,false),
(1004,'2022-03-10','2022-03-15',13 ,true ),
(1005,'2022-03-15','2022-03-15',5, true  );

核心逻辑:

进行外部连接,我们找到匹配项和不匹配项,这意味着我们可以解决需要停用的“陈旧行”

SELECT t.d as td, s.*
FROM (SELECT * FROM trg_table where active_flag and date >= '2022-03-01') t
FULL OUTER JOIN src_table s ON t.d = s.d
order by 1;

编入 MERGE 的核心只有规则 1 和 3 需要工作:

MERGE INTO trg_table t using (
    SELECT t.d as td, s.*
    FROM (
        SELECT * 
        FROM trg_table 
        where active_flag and date >= '2022-03-01'
    ) t
    FULL OUTER JOIN src_table s 
        ON t.d = s.d
) s on s.td = t.d 
WHEN MATCHED AND t.date >= '2022-03-01' AND s.d is null then update set active_flag = false
WHEN NOT MATCHED THEN INSERT values (s.d, s.date, s.updated_at, s.metre, s.active_flag);

给出:

D DATE UPDATED_AT METRE ACTIVE_FLAG
1,001 2022-01-01 2022-01-01 10 TRUE
1,002 2022-01-02 2022-01-02 15 TRUE
1,003 2022-03-01 2022-03-01 20 FALSE
1,004 2022-03-10 2022-03-10 10 FALSE
1,004 2022-03-10 2022-03-15 13 TRUE
1,005 2022-03-15 2022-03-15 5 TRUE
1,006 2022-03-15 2022-03-15 10 TRUE
1,007 2022-03-20 2022-03-20 1 TRUE