使用另一个具有重复项的表中的数据更新oracle中的表

时间:2017-01-10 17:36:27

标签: sql oracle

我有两个Oracle表,表车和表汽车。我正在更新Car以添加汽车品牌和型号中存在的两个字段。两个表都有3个外围键,Code1,Code2和Code3,它们将我们需要的至少一个键匹配以更新表格,并且列可以为空,因此我们必须小心。这些代码对于每个记录都是唯一的,除了我在下面提到的重复的情况。为了形象化,让我在这里制作表格:

桌车

   ID | Code1 | Code2| Code3| Color | Salesman
    1  1A2B3C   555HGG H1H1H1  Red     John
    2  2H4H6H   777JHH J1J1J1  Blue    Steve
    3  3J7K4A   222QYY I1I1I1  Yellow  Maria
    4                  K2K2K2  Pink    Clara
    5           999YII         Red     Tim

Table Automobile

Code1| Code2| Code3 | Make  | Model  | ID
1A2B3C 555HGG H1H1H1  Nissan  Sentra   234
2H4H6H        J1J1J1  Chevy   Malibu   235
              K2K2K2  Nissan  Maxima   236
              K2K2K2  Nissan  Maxima   237
       999YII         Ford    Focus    238

更新了表车:

   ID | Code1 | Code2| Code3| Color | Salesman | Make | Model
    1  1A2B3C   555HGG H1H1H1  Red     John      Nissan Sentra
    2  2H4H6H   777JHH J1J1J1  Blue    Steve     Chevy  Malibu
    3  3J7K4A   222QYY I1I1I1  Yellow  Maria
    4                  K2K2K2  Pink    Clara     Nissan Maxima
    5           999YII          Red    Tim       Ford   Focus

所以Table Car最初没有Make和Model字段,但我们需要从table Automobile中获取。假设现在表中存在字段,只需要填充。此外,您可以在表汽车的日产千里马示例中看到具有唯一ID的重复记录。在那种情况下,我只需要其中一条记录并不重要,因为来自汽车的ID无关紧要且不需要。两个ID字段没有连接。将填充至少一个代码字段,永远不会出现全部为空的情况。我知道这是一个有点混乱的问题,所以如果你需要澄清请求,我会调整我的OP。此外,这也是针对Oracle的,请记住这一点。任何帮助将不胜感激,这已经困扰了我好几天。

2 个答案:

答案 0 :(得分:0)

以下使用row_number()获取一行,然后匹配代码:

select c.*, a.make, a.model
from car c left join
     (select a.*,
             row_number() over (partition by code1, code2, code3 order by id) as seqnum
      from automobile a
     ) a
     on (c.code1 = a.code1 or c.code1 is null and a.code1 is null) and
        (c.code2 = a.code2 or c.code2 is null and a.code2 is null) and
        (c.code3 = a.code2 or c.code3 is null and a.code3 is null) and
        a.seqnum = 1

答案 1 :(得分:0)

加入OR条件非常慢,因为它们无法利用列上的索引。 (如果您在表中的Code1Code2Code3上有索引,将会有所帮助。)我宁愿将作业分成三个单独的更新,一次只使用一列。此外,在第二次和第三次更新中,我将检查新列中的NULL以确保我不将行更新为它已包含的相同值(这可能看起来像一个小问题,但撤消和重做可能会在冗余分配之上增加大量开销。)

由于您需要对Automobile表进行重复数据删除,因此最好创建一个临时表(因为您将使用它三次)。类似的东西:

create global temporary table auto
on commit preserve rows    -- if you want to commit after each update
as (
     select code1, code2, code3, min(make) as make, min(model) as model
     from   automobile
     group by code1, code2, code3
   )

然后第二次更新,使用code2code3将类似,code1不需要where子句。您会看到我更喜欢merge语句,但您可以将update与联接一起使用。

merge into car c
  using auto a
  on (c.code2 = a.code2)
when matched then update
     set c.make  = a.make,
         c.model = a.model
     where c.make is null
;