Poiché non conosci la struttura in anticipo, a causa del pivot dinamico su un numero sconosciuto di colonne nel set di risultati, puoi utilizzare un cursore di riferimento per recuperare il risultato della query dinamica.
Questo utilizza variabili di collegamento SQL*Plus/SQL Developer/SQLcl;
variable rc refcursor;
declare
sql_stmt clob;
pivot_clause clob;
begin
select listagg('''' || TO_CHAR(PERIOD_NAME,'MON-YY') || ''' as "' || TO_CHAR(PERIOD_NAME,'MON-YY') || '"', ',')
within group (order by PERIOD_NAME)
into pivot_clause from (select TO_DATE(PERIOD_NAME,'MON-YYYY') PERIOD_NAME
from table1
where request_id=<id>
GROUP BY TO_DATE(PERIOD_NAME,'MON-YYYY')
order by TO_DATE(PERIOD_NAME,'MON-YYYY') ASC);
sql_stmt := 'select * from (select PERIOD_NAME, depreciation
from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';
open :rc for sql_stmt;
end;
/
print rc
variable rc refcursor;
dichiara la variabile e il tipo di dati della variabile di binding client, come cursore di riferimento. Quindi, invece di usare execute immediate
fa aperto per con la tua dichiarazione dinamica:
open :rc for sql_stmt;
che apre il cursore di riferimento con i risultati di quella query. (Nota il :
all'inizio di :rc
, indicando che si tratta di un riferimento a una variabile di collegamento e non di una variabile PL/SQL locale).
Quindi fuori dal blocco puoi stampare il risultato impostato con:
print rc
Diversi client/IDE avranno bisogno di una sintassi diversa. Potresti fare qualcosa di simile anche su JDBC. Potresti anche avere una funzione che restituisce un sys_refcursor
. Ma dipende dal tuo obiettivo finale per questo.
Per inciso, al momento otterrai un valore nullo per tutti i totali ruotati; la tua query finale deve ottenere PERIOD_NAME
nello stesso formato che sta cercando la clausola pivot, ad es.
sql_stmt := 'select * from (select to_char(to_date(PERIOD_NAME, ''MON-YYYY''), ''MON-YY'') as PERIOD_NAME, depreciation
from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';
anche se sarebbe leggermente più semplice lasciare invece il formato originale nella clausola pivot:
declare
sql_stmt clob;
pivot_clause clob;
begin
select listagg('''' || PERIOD_NAME || ''' as "' || TO_CHAR(PERIOD_DATE,'MON-YY') || '"', ',')
within group (order by PERIOD_DATE)
into pivot_clause from (select distinct PERIOD_NAME, TO_DATE(PERIOD_NAME,'MON-YYYY') PERIOD_DATE
from table1
where request_id=<id>);
sql_stmt := 'select * from (select PERIOD_NAME, depreciation
from table1) pivot (sum(depreciation) for PERIOD_NAME in (' || pivot_clause || '))';
open :rc for sql_stmt;
end;
/
Con una tabella fittizia e dati:
create table table1 (request_id, period_name, depreciation) as
select 1, 'JAN-2018', 42 from dual
union all select 1, 'FEB-2018', 11 from dual
union all select 1, 'MAR-2018', 22 from dual
union all select 1, 'MAR-2018', 33 from dual
union all select 2, 'MAR-2018', 44 from dual;
eseguendo una delle versioni e facendo print rc
mostra:
JAN-18 FEB-18 MAR-18
---------- ---------- ----------
42 11 99