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 哪种方式更具成本效益?我想性能应该是一样的。我还假设我可以忽略插入成本。谢谢!
你能使用“神奇”的数字或 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)