Ponieważ nie znasz z góry struktury, z powodu dynamicznego przestawiania do nieznanej liczby kolumn w zestawie wyników możesz użyć kursora ref, aby pobrać wynik dynamicznego zapytania.
To używa zmiennych wiązania 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;
deklaruje zmienną i typ danych zmiennej wiążącej klienta jako kursor referencyjny. Wtedy zamiast używać execute immediate
to otwarte dla za pomocą dynamicznego zestawienia:
open :rc for sql_stmt;
który otwiera kursor ref z wynikami tego zapytania. (Zwróć uwagę na :
na początku :rc
, wskazując, że jest to odwołanie do zmiennej wiążącej, a nie lokalna zmienna PL/SQL).
Następnie poza blokiem możesz wydrukować zestaw wyników z:
print rc
Różni klienci/IDE będą potrzebować innej składni. Możesz też zrobić coś podobnego w JDBC. Możesz także mieć funkcję, która zwraca sys_refcursor
. Ale to zależy od tego, jaki jest Twój ostateczny cel.
Nawiasem mówiąc, w tej chwili uzyskasz wartość null dla wszystkich przestawianych sum; Twoje ostatnie zapytanie musi uzyskać PERIOD_NAME
w tym samym formacie, którego szuka klauzula pivot, np.
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 || '))';
chociaż nieco prościej byłoby pozostawić oryginalny format w klauzuli 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;
/
Z fikcyjną tabelą i danymi:
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;
uruchamianie dowolnej wersji i wykonywanie print rc
pokazuje:
JAN-18 FEB-18 MAR-18
---------- ---------- ----------
42 11 99