从另一个表数据更新表中的多个列,包括空值

Posted

技术标签:

【中文标题】从另一个表数据更新表中的多个列,包括空值【英文标题】:Update multiple columns in a table from another tables data including nulls 【发布时间】:2017-03-08 22:37:03 【问题描述】:

我有两个包含 6 列的表,在一个表(我要更新的那个)中,前三列已经填充,另外三列是我刚刚创建的,所以它们是空的。

汇总表

Number, ID, height, weight, volume, density
1        1     5       
2        2     5
3        3     12

我有另一个完全填充的表,其中使用了相同的 ID,但其他数据波动并且没有高度

每日餐桌

Number, ID, name, weight, volume, density
1       1    c3     23               10
2       2    c17    24.2    1        5
3       3    c12    22      2        6
4       1    c3     21      2
5       2    c17    25               8

我想从 Daily 表中获取最后的重量、体积、密度值,并使用它们来填充 Summary 表中的这些列。两张表都有数千个条目,每天接近一百万个。

结果应该是汇总表更改

Number, ID, height, weight, volume, density
1       1     5      21      2   
2       2     5      25               8
3       3     12     22      2        6

我可以使用从this question 获得的信息一点一点地完成它,但我想一次性完成。 请帮忙。

【问题讨论】:

如何识别日表中的“最后”行?我没有看到任何时间戳或类似的东西 @a_horse_with_no_name 它们是编号的行,抱歉现在应该是六列我明白你的意思了,我会编辑 【参考方案1】:

类似这样的:

update summary 
  set weight = t.weight,
      volume = t.volume, 
      density = t.density
from (
  select distinct on (id) id, weight, volume, density
  from daily
  order by id, number desc
) t
where t.id = summary.id;

内部选择将只返回每日表中每个 id 具有最高“数字”的行。其他解决方法见greatest-n-per-group

在线示例:http://rextester.com/AWT29305

【讨论】:

非常适合我的需求,又好又简单【参考方案2】:

试试这个:

with Daily as (
select d.number, d.Id, d.weight, d.volume, d.density 
From  daily d 
join (select id, max(number) from daily group by ID) d2 on d.number = d2.number
)
update Summary
set weight = d2.weight
, volume = d2.volume
, density = d2.density
from Daily d2
where id = d2.id
and
(weight<> d2.weight OR
volume <> d2.volume OR
density <> d2.density)
)

这应该确保您获得每个 id 的正确最新记录,并且只获得那些需要更新的记录。

【讨论】:

我花了一段时间才明白这一点,但效果很好【参考方案3】:

您可以使用窗口函数来获取每日表中每个 ID 的最新条目。我已经在 SQL Server 中对此进行了测试,但我相信 postgres 的语法在这种情况下是相同的。

With LatestDaily As
(
  select *
  from (
    Select RANK() OVER (Partition By ID ORDER BY Number DESC) as r, *
    From Daily
  ) t
  where t.r = 1
)
Update summary s
   Set Weight = d.Weight, Volume = d.Volume, Density = d.Density
From LatestDaily d 
where s.ID = d.ID;

【讨论】:

Postgres 在末尾需要;,而不是在开头。当使用 distinct on() 而不是窗口函数时,Postgres 中的“greatest-n-per-group”问题通常更快。而 update 的连接语法在 Postgres 中是不同的。您应该from 子句中重复目标表。 好收获。谢谢!我想知道 sql server 是否有相当于 postgres 的 distinct on()。这是一个简洁的功能。 我冒昧地修复了您语句中的语法错误。【参考方案4】:

更新摘要 SET weight = _weight, volume = _volume, density =_density 从 ( SELECT ID _ID、重量_重量、体积_体积、密度_密度 来自详细信息 WHERE Number IN (SELECT MAX(Number) FROM Details GROUP BY ID) ) WHERE ID = _ID

【讨论】:

以上是关于从另一个表数据更新表中的多个列,包括空值的主要内容,如果未能解决你的问题,请参考以下文章

Spark 从另一个表更新 Delta 中的多个列

无法更新表中的列 它返回单行子查询返回多个

SQL 从另一个表中的另一列更新一列

更新两个表中的数据。一种在一列中包含多个数据

使用 MSSQL 中的 DYNAMIC SQL 从另一个表更新一个表中的值

如何使用 SQL 查询从另一个表中更新作为下拉列表的字段