在 SQL 中处理“不匹配时”(如何正确合并)

Posted

技术标签:

【中文标题】在 SQL 中处理“不匹配时”(如何正确合并)【英文标题】:Messing with 'when not matched' in SQL (how to merge properly) 【发布时间】:2013-03-26 15:28:27 【问题描述】:

我正在创建几个表并将它们中的数据合并到一个表中。这些表具有相似的 col1 和 col2 列,但这些列中的值可以不同,例如。 tab1 的第 1 行上的 col1 可能有“0”,而 tab2 中的 col1 可能在 col1“1”的同一行上。只有在这种情况下,我才需要更新第 1 行 col1 中 tab1 的值。请看以下示例:

BEFORE MERGING               
tab1:
id col1 col2
1  0    0
2  0    1
3  0    0
                              AFTER MERGING WITH tab2
tab2:                         tab1:
id col1 col2                   id col1 col2
1  1    0           --->       1  1    0
2  0    0                      2  0    1
3  0    0                      3  0    0

为此,我使用以下查询:

merge into tab1 st
   using (select id, col1, col2 from tab2) ss
   ON (st.id=ss.id)
    when matched then 
    update set  st.col1 = ss.col1,
                st.col2 = ss.col2 

  where ss.col1 != 0 or ss.col2 != 0
  when not matched then
    insert (st.id, st.col1, st.col2)
    values (ss.id, ss.col1, ss.col2)
    ; 

我只是在学习 sql,所以直到现在我才注意到这个查询不正确。它可以用来自tab2的“0”覆盖tab1中的“1”值。请帮我改进这个查询,我卡住了。

【问题讨论】:

您使用的是 mysql 还是 Oracle?没想到 MySQL 支持 Merge... 这是一个简化版本,实际上我创建了 4 个表并尝试将它们与第一个表合并,仅更新 != 0 的单元格。我想知道“当 col1 不匹配时”这样的条件col2 然后插入 col2 值 col2" 可以在这里实现... 我用oracle,误导大家见谅 【参考方案1】:

您可以在设置值时使用 CASE 表达式来控制分配的值。尝试类似:

merge into tab1 st
   using (select id, col1, col2 from tab2) ss
   ON (st.id=ss.id)
    when matched then 
    update set  st.col1 = CASE WHEN st.col1 = 0 THEN ss.col1 ELSE st.col1 END,
                st.col2 = CASE WHEN st.col2 = 0 THEN ss.col2 ELSE st.col2 END

  where ss.col1 != 0 or ss.col2 != 0
  when not matched then
    insert (st.id, st.col1, st.col2)
    values (ss.id, ss.col1, ss.col2)
    ; 

因此在 WHEN MATCHED 情况下,如果 tab1 (st) 的值为零,则将其更改为 tab2 (ss) 的值,否则只需将 tabl1 的值设置为自身。

分享和享受。

【讨论】:

【参考方案2】:

您应该使用ss.coln, st.coln 的最大值进行更新。例如,使用GREATEST:

MERGE INTO tab1 st
USING (SELECT id, col1, col2 FROM tab2) ss
ON (st.id = ss.id)
WHEN MATCHED THEN
   UPDATE
      SET st.col1 = greatest(ss.col1, st.col1), 
          st.col2 = greatest(ss.col2, st.col2)
    WHERE ss.col1 > st.col1
       OR ss.col2 > st.col2
WHEN NOT MATCHED THEN
   INSERT (st.id, st.col1, st.col2) 
   VALUES (ss.id, ss.col1, ss.col2);

【讨论】:

非常感谢,我将使用您的解决方案,它有点短;)

以上是关于在 SQL 中处理“不匹配时”(如何正确合并)的主要内容,如果未能解决你的问题,请参考以下文章

HSQLDB QUERY 正确性

sql server 在不匹配时与多个插入合并

如何以正确的方式处理结果集?

如何正确处理 spark.sql.AnalysisException

Amazon Redshift:当找到的表 id 不匹配时,如何将 `stl_load_errors` 行与正确的表名相关联?

用于更改跟踪表的 Snowflake snowsql 合并语句 - 当目标/源不匹配时,不允许