実行時に列が不明な結果に動的SQLを使用することは、他の特定のRDMBSと比較して、Oracleでは少し面倒です。
出力のレコードタイプはまだ不明であるため、事前に定義することはできません。
Oracle 11gでは、1つの方法は、ピボットされた結果で一時テーブルを生成する名前のないプロシージャを使用することです。
次に、その一時テーブルから結果を選択します。
declare
v_sqlqry clob;
v_cols clob;
begin
-- Generating a string with a list of the unique names
select listagg(''''||CCL||''' as "'||CCL||'"', ', ') within group (order by CCL)
into v_cols
from
(
select distinct CCL
from tableA
);
-- drop the temporary table if it exists
EXECUTE IMMEDIATE 'DROP TABLE tmpPivotTableA';
EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF;
-- A dynamic SQL to create a temporary table
-- based on the results of the pivot
v_sqlqry := '
CREATE GLOBAL TEMPORARY TABLE tmpPivotTableA
ON COMMIT PRESERVE ROWS AS
SELECT *
FROM (SELECT ID, CCL, Flag FROM TableA) src
PIVOT (MAX(Flag) FOR (CCL) IN ('||v_cols||')) pvt';
-- dbms_output.Put_line(v_sqlqry); -- just to check how the sql looks like
execute immediate v_sqlqry;
end;
/
select * from tmpPivotTableA;
返品:
ID adam john rob terry
-- ---- ---- --- -----
1 x x x
2 x
db<>fiddleここでテストを見つけることができます
Oracle 11gでは、使用する別のクールなトリック(Anton Schefferによって作成された)がこのブログにあります。ただし、ピボット関数を追加する必要があります。
ソースコードはこのzipにあります
その後、SQLは次のように単純になります。
select * from
table(pivot('SELECT ID, CCL, Flag FROM TableA'));
db<>fiddleここでテストを見つけることができます