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

Istruzione di aggiornamento Oracle con funzione di gruppo

Hai due record in ogni tabella dove area è 01 e devi impostarli su valori diversi per soddisfare la chiave primaria:non puoi impostarli entrambi sul valore massimo o minimo dalla seconda tabella, quindi non vuoi davvero fare alcun raggruppamento.

Non sembra esserci nessun altro ordinamento tra record con la stessa area , quindi presumo che sia arbitrario e non importa quale record per ciascuna area ottiene quale branch_code dall'altro tavolo. Se non è arbitrario, allora le regole dovrebbero essere specificate...

Un aggiornamento correlato è complicato se è necessario eseguire una corrispondenza su un ordine arbitrario all'interno di un gruppo di record. Hai bisogno di un modo per identificare l'ordine delle righe, ma aggiungendo un row_number() colonna alle tabelle originali per creare una vista in linea comporterà un errore ORA-01732.

Tuttavia, puoi utilizzare il rowid della tabella di destinazione pseudocolonna; devi solo fare un ulteriore join nella correlazione per ottenere lo stesso valore insieme al nuovo branch_code . Qualcosa come:

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;

Che ti dà:

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           

Ora in realtà non hai bisogno di tutte quelle colonne, hai solo bisogno del rid (il branch_cp.rowid ) e il correlato branch_cp_2.branch_code .

Ma vuoi anche aggiornare solo quando c'è una corrispondenza - per annullare l'annullamento di qualsiasi riga in cui non c'è alcun valore nell'altra tabella - quindi dovresti ripetere quel join in exists sottoquery.

È più semplice eseguire un 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.

La tua tabella ora ha:

select * from branch_cp;

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

SQL Fiddle .