BigQuery Merge - 如果未匹配则插入新行

Guy*_*Guy 6 sql google-bigquery

我正在尝试在 Google BigQuery(ETL 过程的一部分)中编写合并查询。

有源(暂存)和目标表,我有两种合并数据的方法:经典的“Upsert”合并或如果所有列都不匹配则插入新行。

这是第一种方式(经典的“ Upsert ”)查询的示例:

MERGE DS.Target T
USING DS.Source S
ON T.Key=S.Key    
WHEN NOT MATCHED THEN
  INSERT ROW
WHEN MATCHED THEN
  UPDATE SET Col1 = S.Col1, Col2 = S.Col2
Run Code Online (Sandbox Code Playgroud)

这样,如果键存在,它总是更新列的值,即使值相同。此外,这仅在密钥不可为空时才有效。

另一种方法是在值不匹配时插入新行

MERGE DS.Target T
USING DS.Source S
ON T.A = S.A and T.B = S.B and T.C = S.C
WHEN NOT MATCHED THEN
INSERT ROW
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方式,但我发现当列类型为 NULL 时这是不可能的,因为 NULL != NULL 然后当值为 Null 时条件为假。

我找不到编写此查询和处理空值比较的正确方法。

无法在合并条件下检查 Null,例如:

ON ((T.A IS NULL and S.A IS NULL) or T.A = S.A)
WHEN NOT MATCHED THEN
INSERT ROW
Run Code Online (Sandbox Code Playgroud)

错误信息:

如果没有连接两侧字段相等的条件,则不能使用 RIGHT OUTER JOIN。

也不可能在WHERE子句中使用目标表引用,例如:

ON T.A = S.A
WHEN NOT MATCHED AND 
   S.A IS NOT NULL AND T.A IS NOT NULL
THEN
   INSERT ROW
Run Code Online (Sandbox Code Playgroud)

你有什么建议?另外,让我们说两种方式都是可能的,BQ 哪种方式更具成本效益?我想性能应该是一样的。我还假设我可以忽略插入成本。谢谢!

Fel*_*ffa 3

你能使用“神奇”的数字或 ID 吗?

这有效:

CREATE OR REPLACE TABLE temp.target AS
SELECT * FROM UNNEST(
  [STRUCT(1 AS A, 2 AS B, 3 AS C, 5 AS d)
   , (null, 1, 3, 500)
  ]);
CREATE OR REPLACE TABLE temp.source AS
SELECT * FROM UNNEST(
  [STRUCT(1 AS A, 2 AS B, 3 AS C, 100 AS d)
   , (1, 1, 1, 1000)
   , (null, null, null, 10000)
   , (null, 1, 3, 10000)
  ]);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在此输入图像描述

MERGE temp.target T
USING temp.source S
ON IFNULL(T.A, -9999999) = IFNULL(S.A, -9999999) and IFNULL(T.B, -9999999) = IFNULL(S.B, -9999999) and IFNULL(T.C, -9999999) = IFNULL(S.C, -9999999)
WHEN NOT MATCHED THEN
INSERT ROW;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述