sql >> Databasteknik >  >> RDS >> Oracle

Oracle update statement med gruppfunktion

Du har två poster i varje tabell där area är 01 , och du måste ställa in dem på olika värden för att uppfylla primärnyckeln - du kan inte ställa in dem båda till max- eller minvärde från den andra tabellen, så du vill egentligen inte göra någon gruppering.

Det verkar inte finnas någon annan ordning mellan poster med samma area , så jag antar att det är godtyckligt och att det inte spelar någon roll vilken post för varje area får vilken branch_code från det andra bordet. Om det inte är godtyckligt måste reglerna specificeras...

En korrelerad uppdatering är knepig om du behöver matcha i en godtycklig ordning inom en grupp av poster. Du behöver något sätt att identifiera radordningen, men att lägga till en row_number() kolumnen till de ursprungliga tabellerna för att skapa en inlinevy kommer att leda till ett ORA-01732-fel.

Du kan dock använda måltabellens rowid pseudokolonn; du behöver bara göra en extra join i korrelationen för att få samma värde tillsammans med den nya branch_code . Något i stil med:

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;

Vilket ger 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 behöver du faktiskt inte alla dessa kolumner, du behöver bara rid (den branch_cp.rowid ) och den korrelerade branch_cp_2.branch_code .

Men du vill också bara uppdatera när det finns en matchning - för att ogiltigförklara alla rader där det inte finns något värde i den andra tabellen - så du måste upprepa den kopplingen i exists underfråga.

Det är enklare att göra 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.

Ditt bord har nu:

select * from branch_cp;

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

SQL Fiddle .




  1. Node.js ansluter via ssh

  2. MySQL IN-operatörens prestanda på (stort?) antal värden

  3. Det gick inte att kontakta pgAdmin 4-servern:Allvarligt fel

  4. Hur importerar jag en SQL-fil till databasen och ignorerar X-rader i filen?