sql >> Database teknologi >  >> RDS >> Oracle

Oracle opdateringserklæring med gruppefunktion

Du har to poster i hver tabel, hvor area er 01 , og du skal indstille dem til forskellige værdier for at tilfredsstille den primære nøgle - du kan ikke indstille dem begge til maks. eller min. værdi fra den anden tabel, så du ønsker ikke rigtig at foretage nogen gruppering.

Der ser ikke ud til at være nogen anden rækkefølge mellem poster med det samme area , så jeg antager, at det er vilkårligt, og det er ligegyldigt, hvilken post for hvert area får hvilken branch_code fra det andet bord. Hvis det ikke er vilkårligt, skal reglerne specificeres...

En korreleret opdatering er vanskelig, hvis du skal matche i en vilkårlig rækkefølge inden for en gruppe af poster. Du har brug for en måde at identificere rækkefølgen på, men at tilføje en row_number() kolonne til de originale tabeller for at oprette en inline-visning vil føre til en ORA-01732-fejl.

Du kan dog bruge måltabellens rowid pseudokolonne; du skal bare gøre en ekstra joinforbindelse i korrelationen for at få den samme værdi sammen med den nye branch_code . Noget som:

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;

Hvilket giver dig:

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           

Nu har du faktisk ikke brug for alle disse kolonner, du har kun brug for rid (den branch_cp.rowid ) og den korrelerede branch_cp_2.branch_code .

Men du vil også kun opdatere, når der er et match - for at annullere alle rækker, hvor der ikke er nogen værdi i den anden tabel - så du bliver nødt til at gentage den join i exists underforespørgsel.

Det er nemmere at lave en merge :

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.

Dit bord har nu:

select * from branch_cp;

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

SQL Fiddle .




  1. Hvordan forskønner man det output, der kommer fra SELECT-forespørgslen i kommandoprompten?

  2. Sådan installeres (L|M)AMP-stack på iPhone?

  3. Er det muligt at slå tilbudsbehandling fra i Postgres COPY-kommandoen med CSV-format?

  4. PSQLE Undtagelses- og låseproblem, når trigger tilføjes på tabellen