Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle-Update-Anweisung mit Gruppenfunktion

Sie haben zwei Datensätze in jeder Tabelle, in denen area ist 01 , und Sie müssen sie auf unterschiedliche Werte setzen, um den Primärschlüssel zu erfüllen - Sie können sie nicht beide auf den maximalen oder minimalen Wert aus der zweiten Tabelle setzen, also möchten Sie nicht wirklich gruppieren.

Es scheint keine andere Reihenfolge zwischen Datensätzen mit demselben area zu geben , also gehe ich davon aus, dass es willkürlich ist und es keine Rolle spielt, welcher Datensatz für jeden area verwendet wird bekommt welchen branch_code vom anderen Tisch. Wenn es nicht willkürlich ist, müssten die Regeln spezifiziert werden...

Eine korrelierte Aktualisierung ist schwierig, wenn Sie innerhalb einer Gruppe von Datensätzen in einer beliebigen Reihenfolge übereinstimmen müssen. Sie brauchen eine Möglichkeit, die Zeilenreihenfolge zu identifizieren, aber fügen Sie eine row_number() hinzu Spalte zu den Originaltabellen hinzu, um eine Inline-Ansicht zu erstellen, führt zu einem ORA-01732-Fehler.

Sie können jedoch die rowid der Zieltabelle verwenden Pseudospalte; Sie müssen nur einen zusätzlichen Join in der Korrelation durchführen, um denselben Wert zusammen mit dem neuen branch_code zu erhalten . Etwas wie:

select bc.rid,
  bc.area,
  bc.branch_code,
  bc.branch_name,
  bc2.area,
  bc2.branch_code,
  bc2.branch_name
from (
  select bc.*,
    bc.rowid as rid,
    row_number() over (partition by bc.area order by bc.branch_code) as rn
  from branch_cp bc
) bc
join (
  select bc2.*,
    row_number() over (partition by bc2.area order by bc2.branch_code) as rn
  from branch_cp_2 bc2
) bc2
on bc2.area = bc.area
and bc2.rn = bc.rn;

Das ergibt:

RID                AREA  BRANCH_CODE BRANCH_NAME AREA  BRANCH_CODE BRANCH_NAME
------------------ ----- ----------- ----------- ----- ----------- -----------
AAAwy+AAEAAAA0DAAA 01    01          A           01    04          D           
AAAwy+AAEAAAA0DAAB 01    02          B           01    05          E           
AAAwy+AAEAAAA0DAAC 03    03          C           03    06          F           

Jetzt brauchen Sie nicht alle diese Spalten, Sie brauchen nur die rid (die branch_cp.rowid ) und dem zugehörigen branch_cp_2.branch_code .

Aber Sie möchten auch nur aktualisieren, wenn es eine Übereinstimmung gibt - um das Nullen von Zeilen zu annullieren, in denen es keinen Wert in der anderen Tabelle gibt - also müssten Sie diesen Join in exists wiederholen Unterabfrage.

Es ist einfacher, eine merge durchzuführen :

merge into branch_cp bc
using (
  select bc.rid,
      bc2.branch_code
    from (
      select bc.*,
        bc.rowid as rid,
        row_number() over (partition by bc.area order by bc.branch_code) as rn
      from branch_cp bc
    ) bc
    join (
      select bc2.*,
        row_number() over (partition by bc2.area order by bc2.branch_code) as rn
      from branch_cp_2 bc2
    ) bc2
    on bc2.area = bc.area
    and bc2.rn = bc.rn
) bc2
on (bc.rowid = bc2.rid)
when matched then update set bc.branch_code = bc2.branch_code;

3 rows merged.

Ihre Tabelle hat jetzt:

select * from branch_cp;

AREA  BRANCH_CODE BRANCH_NAME
----- ----------- -----------
01    04          A           
01    05          B           
03    06          C           

SQL-Geige .