仅当连接明确时才更新行

Posted

技术标签:

【中文标题】仅当连接明确时才更新行【英文标题】:Update rows only when a join is unambiguous 【发布时间】:2018-10-11 17:10:44 【问题描述】:

我有两个表,ab,都带有 product_namevaluea 中的 value 列为 null。

我想用b 表中的值更新a 表。由于数据中的一个怪癖,product_name 在任一表中都不是唯一的。

我只想在两者之间在product_name 上存在一个明确匹配时设置该值。当a 中的多行具有相同的产品名称,或者b 中的多行匹配时,我想将该值保留为空。在 Postgres 中有没有一种有效的方法来做到这一点?

一个更简单的版本是在a 中首先使用identify unique product names。然后,更新 b 中只有一行匹配的行——但我也不确定如何编写该约束。

【问题讨论】:

【参考方案1】:

简单的方法:

update a
set value = (select min(b.value) from b where b.product_name = a.product_name)
where product_name in (select product_name from a group by product_name having count(*) = 1)
  and product_name in (select product_name from b group by product_name having count(*) = 1)
;

【讨论】:

(explain.depesz.com/s/SLZx) 与 (explain.depesz.com/s/NBon)【参考方案2】:

你可以使用聚合:

update a
   set value = b.value
   from (select b.product_name, max(b.value) as value
         from b
         group by b.product_name
         having min(b.value) = max(b.value)  -- there is only one value
        ) b
   where b.product_name = a.product_name;

请注意,这假定b.value 不是null。如果需要,很容易包含 null 值的逻辑。

【讨论】:

【参考方案3】:

把 [How to Select Every Row Where Column Value is NOT Distinct 和 @Gordon Linoff 的回答放在一起:

create table a (
     id serial primary key
    ,product_name text 
    ,value int
);

create table b (
     id serial primary key
    ,product_name text 
    ,value int not null
);

insert into a (product_name) values
   ('A')
   ,('B')
   ,('C')
   ,('D')
   ,('E')
   ,('E');


insert into b (product_name,value) values
    ('A',1)
   ,('A',1) 
   ,('B',42)
   ,('C',1)
   ,('C',2)
   ,('E',1)
;

update a
   set value = b.value
   from (select product_name, min(value) as value
         from b
         group by b.product_name
         having 1 = count(*)
        ) b
   where b.product_name = a.product_name
     and a.product_name not in
     (select product_name
        from a
        group by product_name
        having 1 < count(*));

@Gordon Lindof 如果 product_name 和 value 在 b 中都重复(例如 product_name=A)并且错过了要求 product_name not 在 a 中重复,则您的答案将失败。

【讨论】:

以上是关于仅当连接明确时才更新行的主要内容,如果未能解决你的问题,请参考以下文章

仅当所有匹配条件都失败时才更新标志

仅当表中不存在该值时才更新 SQL 列

仅当记录匹配时才从另一个表中更新记录

仅当字段为空时才更新来自 select 语句的查询

仅当烧瓶中的变量发生变化时才更新网站

仅当自动增量数据相等时才从另一个表列更新 mysql 列