在 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
我有两个 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 |