【问题标题】:SQL - Conditionally join and replace values between two tablesSQL - 有条件地连接和替换两个表之间的值
【发布时间】:2023-03-24 04:15:01
【问题描述】:

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

我想要一个符合以下条件的查询:

  • 从第一个表中选择所有行
  • 如果第二个表中有匹配的行(即当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

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

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

SELECT * FROM raw_d

选择“每组最大 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;

我计划像Replace column values based on another dataframe python pandas - better way? 那样合并数据。

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

【问题讨论】:

    标签: python sql database pandas postgresql


    【解决方案1】:

    我建议将要求表述为:

    • 从第二个表中选择最近的一行
    • 从第一个表中引入其他不匹配的行

    这是union alldistinct 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
                     );
    

    【讨论】:

      【解决方案2】:

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

      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
      

      DEMO

      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
      

      DEMO

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-15
        • 1970-01-01
        相关资源
        最近更新 更多