Domanda

Ho una query di grandi dimensioni (non scritta da me, ma sto apportando alcune modifiche). Una cosa che mi dà fastidio è che ho la stessa funzione COALESCE in circa quattro posti. C'è un modo per capirlo, possibilmente unendosi a una selezione di DUAL? C'è un vantaggio in termini di prestazioni nel factoring?

Ecco la query leggermente sconcertata:

select 
tbl1.gid
[snip]
         ,COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
        ,t1_end_dt
FROM    tbl1
....
JOIN    tbl2               ON (t2_pk          = wpck_wrkr_id  AND
                                            t2_ind_1    ='Y'    AND
        COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN  t2_strt_dt AND t2_end_dt)
JOIN    tbl3                ON (t3_pk               = t2_fk_t3_pk AND
       COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN t3_strt_dt AND t3_end_dt)    
LEFT JOIN tbl4 tbl4_a             ON (tbl4_a.t4_pk         = chkw_wkt_id)
.....
GROUP BY tbl1.gid 
.....
        ,COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
        ,COALESCE(tbl4_b.t4_or_id, tbl4_a.t4_or_id, t7_or_id )
        ,t1_end_dt
ORDER BY perd_end_dt

Nota che ho già preso in considerazione uno dei COALESCE nominandolo pred_end_dt in SELECT e facendo riferimento ad esso con quel nome in ORDER BY.

È stato utile?

Soluzione

Dovresti essere in grado di sostituire l'occorrenza nella clausola GROUP BY con l'alias di colonna perd_end_dt . Ma le occorrenze nelle condizioni JOIN non possono utilizzare l'alias di colonna.

Questo ha un impatto sulle prestazioni. Non credo che il JOIN le condizioni possono utilizzare un indice nel modo in cui sono attualmente scritte. Però, è solo un termine nella condizione JOIN, quindi l'impatto potrebbe essere molto leggera. Cioè, i termini che coinvolgono t2_pk e t2_ind_1 potrebbero già ridurre il set di righe, quindi il confronto delle date deve fare i conti con un piccolo set. Dipende da quante righe stiamo parlando e da come vengono distribuiti i dati.

Un modo per scomporre il COALESCE () e sfruttare l'indicizzazione sarebbe quello di creare una colonna ridondante che è il risultato di quell'espressione. Utilizzare i trigger per assicurarsi che abbia il valore corretto dopo ogni inserimento o aggiornamento. Quindi indicizza la colonna.

Ma come ho detto, potrebbe essere più un problema di quanto valga la pena. Sarebbe più lavoro e dovresti essere sicuro che questa modifica renderebbe il codice più gestibile, più corretto o più veloce.


Un'altra opzione sarebbe quella di definire un alias per l'espressione COALESCE () in una sottoquery. Non posso dire da quali tabelle provengono le colonne, perché non li qualifichi con alias di tabella. Ma se posso supporre sono tutte colonne di tbl1 :

...
FROM (
    SELECT COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) perd_end_dt,
      t1_fk_t2_pk
    FROM tbl1) t1
  JOIN tbl2
    ON (tbl2.t2_pk = t1.t1_fk_t2_pk AND tbl2.t2_ind_1 = 'Y'
      AND t1.perd_end_dt BETWEEN tbl2.t2_strt_dt AND tbl2.t2_end_dt)
...

Altri suggerimenti

Potresti creare una tabella virtuale

(Select Coalesce( all your stuff ....) perdEndDt 
   From [all your tables necessary for this one value])

e includi questo come una tabella unita separata nel tuo Select SQL

  Select [all yr other stuff,
      Z.perdEndDt
  From [Other Tables Joined together]
      Join 
         (Select Coalesce( all your stuff ....) perdEndDt,
               [other columns necessary for join conditions]
         From [all your tables necessary for this one value]) As Z
         On [Join conditions for Z to other tables]
  Where  [any filter predicates]
  Order By Z.perdEndDt
     ... etc.  

Oracle ha viste? (Deve farlo.) Se ti ritrovi a usare quell'espressione COALESCE () in molti luoghi diversi, può valere la pena creare un VISUALIZZA e usarlo al posto dell'originale tavolo (s). Sotto, verranno eseguiti gli stessi calcoli, ma la sintassi delle tue query sarà più concisa e quindi più chiara.

Secondo il mio modo di pensare, " visualizza " è "tabella" in un database come " funzione " è "righe di codice" in un programma. Ogni volta che trovi un sacco di query che usano una logica simile, scrivi una vista che elimina la logica comune e la usi invece.

Forse puoi usare una clausola with?

with data as
(
   select COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
   ,      .....
   ,      ...
   from   tbl1
)
select ...
from   data
,      ....
where  ....
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top