繁体   English   中英

SQL - 有条件地连接和替换两个表之间的值

[英]SQL - Conditionally join and replace values between two tables

我有两个表,其中一个保存“原始”数据,另一个保存“更新”数据。 更新后的数据只包含对第一个表中行的更正,但本质上是相同的。 单独存储此数据是一项功能要求。

我想要一个具有以下条件的查询:

  • Select 第一个表中的所有行
  • 如果第二个表中有匹配的行(即当raw_d.primary_key_col_1 = edit_d.primary_key_col_1raw_d.primary_key_col_2 = edit_d.primary_key_col_2 ),我们使用最新的(其中最新的基于第二个表中的列primary_key_col_3值,而不是第一个
  • 否则,我们使用第一个表中的值。

注意:我在实际数据中有更多的“价值”列。 考虑以下玩具示例,其中我有两个表raw_dedit_d ,它们非常相似,如下所示:

    primary_key_col_1    |    primary_key_col_2    |    value_col_1    |    value_col_2
-------------------------+-------------------------+-------------------+-------------------
           src_1         |         dest_1          |         0         |         1
           src_2         |         dest_2          |         5         |         4
           src_3         |         dest_3          |         2         |         2
           src_4         |         dest_4          |         6         |         3
           src_5         |         dest_5          |         9         |         9

    primary_key_col_1    |    primary_key_col_2    |    primary_key_col_3    |    value_col_1    |    value_col_2
-------------------------+-------------------------+-------------------------+---------------------------------------
           src_1         |         dest_1          |       2020-05-09        |         7         |         0
           src_2         |         dest_2          |       2020-05-08        |         6         |         1
           src_3         |         dest_3          |       2020-05-07        |         5         |         2
           src_1         |         dest_1          |       2020-05-08        |         3         |         4
           src_2         |         dest_2          |       2020-05-09        |         2         |         5

预期结果如下:

    primary_key_col_1    |    primary_key_col_2    |    value_col_1    |    value_col_2
-------------------------+-------------------------+-------------------+-------------------
           src_1         |         dest_1          |         7         |         0
           src_2         |         dest_2          |         2         |         5
           src_3         |         dest_3          |         5         |         2
           src_4         |         dest_4          |         6         |         3
           src_5         |         dest_5          |         9         |         9

我提出的解决方案是使用 Pandas 使用第二个表查询“每个组的最大 n 个”,然后在第一个表的查询中“覆盖”行。

第一个查询只会从第一个表中获取数据:

SELECT * FROM raw_d

对 select“每组最大 n”的第二个查询如下:

SELECT DISTINCT ON (primary_key_col_1, primary_key_col_2) * FROM edit_d
ORDER BY primary_key_col_1, primary_key_col_2, primary_key_col_3 DESC;

我计划合并数据,如基于另一个 dataframe python pandas - 更好的方法? .

有谁知道更好的解决方案,最好只使用 SQL? 作为参考,我使用 PostgreSQL 和 Pandas 作为我的数据堆栈的一部分。

正如我从你的问题中了解到的,有两种方法可以解决这个问题

1. 使用FULL OUTER JOIN

with cte as (
   select distinct on (primary_key_col_1,primary_key_col_2) * from edit_d 
   order by primary_key_col_1, primary_key_col_2, primary_key_col_3 desc
)

select 
coalesce(t1.primary_key_col_1,t2.primary_key_col_1),
coalesce(t1.primary_key_col_2,t2.primary_key_col_2),
coalesce(t1.value_col_1,t2.value_col_1),
coalesce(t1.value_col_2,t2.value_col_2)
from cte t1 
full outer join raw_d t2 
on t1.primary_key_col_1 = t2.primary_key_col_1 
and t1.primary_key_col_2 = t2.primary_key_col_2

演示

2. 使用Union

select  
distinct on (primary_key_col_1, primary_key_col_2) 
primary_key_col_1, primary_key_col_2, value_col_1, value_col_2 

from (
  select * from edit_d 
  union all
  select primary_key_col_1,primary_key_col_2, null as "primary_key_col_3", 
  value_col_1,value_col_2 from raw_d
  order by primary_key_col_1, primary_key_col_2, primary_key_col_3 desc nulls last
  )tab

演示

我建议将要求表述为:

  • select 第二个表的最新行
  • 从第一个表中引入不匹配的其他行

这是一个union all with distinct on

(select distinct on (primary_key_col_1, primary_key_col_2) u.primary_key_col_1, u.primary_key_col_2, u.value_col_1, u.value_col_2
 from updated u
 order by primary_key_col_1, primary_key_col_2, primary_key_col_3 desc
) union all
select r.primary_key_col_1, r.primary_key_col_2, r.value_col_1, r.value_col_2
from raw r
where not exists (select 1
                  from updated u
                  where u.primary_key_col_1 = r.primary_key_col_2 and
                        u.primary_key_col_2 = r.primary_key_col_2
                 );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM