首页 > 解决方案 > 如何根据两个表上的一个字段/列更新行

问题描述

我想使用字段“Id”上的另一个表来更新一个表,这样它就不会创建重复项

假设我的第一个表是Table1,第二个表是Table2。当 Id 匹配时,我想从Table2更新Table1中的行

我知道使用 UNION 函数,但这适用于我只需要考虑单个列的整个列。https://docs.snowflake.com/en/sql-reference/operators-query.html#union-all

我的表格示例

表格1

Id  name    number  value
1   a        8       100
2   b        8       100
3   c        8       100
4   d        8       100

表2

Id  name    number  value
3   c         8      99
4   d         6      100
5   e         7      100

预期产出

Id  name    number  value
1   a        8       100
2   b        8       100
3   c        8        99
4   d        6       100
5   e        7       100

请注意,在输出表中,ID 为 3,4 的行已更新,并插入了新的 ID 5。

PS:如果有人能给我提供 select语句来获取输出表就更好了。

标签: snowflake-cloud-data-platform

解决方案


您正在搜索的构造称为MERGE

CREATE OR REPLACE TABLE trg(Id INT, name VARCHAR,   number INT, value INT)
AS    SELECT 1   ,'a',        8,       100
UNION SELECT 2   ,'b',        8,       100
UNION SELECT 3   ,'c',        8,       100
UNION SELECT 4   ,'d',        8,       100;

CREATE OR REPLACE TABLE src(Id INT, name VARCHAR,   number INT, value INT)
AS    SELECT 3   ,'c',         8,      99
UNION SELECT 4   ,'d',         6,      100
UNION SELECT 5   ,'e',         7,      100;

询问:

MERGE INTO trg
USING src
  ON trg.Id = src.Id
WHEN MATCHED THEN UPDATE SET name = src.name,
                             number = src.number,
                             value = src.value
WHEN NOT MATCHED THEN INSERT (ID, name, number, value) 
                      VALUES (src.Id, src.name, src.number, src.value);

SELECT * FROM trg;

输出:

在此处输入图像描述


编辑:

PS:如果有人能给我提供select语句来获取输出表就更好了。

可以使用 UNION ALL 与 QUALIFY 结合:

WITH cte AS (
  SELECT *, 1 AS priority FROM trg
  UNION ALL
  SELECT *, 0 AS priority FROM src
)
SELECT Id, Name, Number, Value
FROM cte
QUALIFY ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Priority) = 1
ORDER BY Id;

推荐阅读