少し面倒ですが、連結文字列を取得するための階層クエリから始めて、プレーンSQLで実行できます。
select keyvalue, fromtable, colsavailable, rnk,
ltrim(sys_connect_by_path(colsavailable, '||''|''||'), '||''|''||') as path
from ordercols_forview
start with rnk = 1
connect by keyvalue = prior keyvalue
and rnk = prior rnk + 1
and prior dbms_random.value is not null
order by keyvalue, fromtable, colsavailable, rnk;
KEYVALUE FR COLS RNK PATH
---------- -- ---- ---------- --------------------------------------------------
1 A1 NUM1 1 NUM1
1 A1 NUM2 2 NUM1||'|'||NUM2
1 A1 NUM3 3 NUM1||'|'||NUM2||'|'||NUM3
2 B1 NUM1 1 NUM1
2 B1 NUM2 2 NUM1||'|'||NUM2
2 B1 NUM3 3 NUM1||'|'||NUM2||'|'||NUM3
2 B1 NUM4 4 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4
3 C1 NUM1 1 NUM1
3 C1 NUM2 2 NUM1||'|'||NUM2
3 C1 NUM3 3 NUM1||'|'||NUM2||'|'||NUM3
3 C1 NUM4 4 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4
3 C1 NUM5 5 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5
あなたのテーブルには、列の位置を示す、表示していない別の列が実際にあると仮定しました。そうでない場合は、何らかの方法でそれを生成できます。おそらく、ベーステーブル列のcolumn_idに基づいて、アルファベット順などです。 connect-by句には連続した数列が必要です。
次に、2つのユニオンを使用して、これらの列とパスの値のテキスト部分(最終的なテーブルでは別々の行である必要があるため)に加えて、SELECT ...
の追加の部分を取得できます。 およびFROM ...
行。それらのそれぞれは、別の生成されたランク番号を必要とします。これらは、CTEのランキングから生成できます:
with ordercols_forview_cte as (
select keyvalue, fromtable, colsavailable, rnk,
ltrim(sys_connect_by_path(colsavailable, '||''|''||'), '||''|''||') as path
from ordercols_forview
start with rnk = 1
connect by keyvalue = prior keyvalue
and rnk = prior rnk + 1
and prior dbms_random.value is not null
)
select 'CREATE OR REPLACE VIEW ' || s.view_to_be_created || ' AS SELECT ' as text,
s.view_to_be_created, 1 as rnk
from seeding_table s
union all
select 'KEYVALUE,' as text,
s.view_to_be_created, 2 as rnk
from seeding_table s
union all
select o.path || ' AS KEY' || o.rnk
|| case when o.rnk < s.noofcols then ',' end,
s.view_to_be_created, (o.rnk * 2) + 1 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
union all
select o.colsavailable || ' AS NO' || o.rnk
|| case when o.rnk < s.noofcols then ',' end as text,
s.view_to_be_created, (o.rnk * 2) + 2 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
union all
select 'FROM ' || o.fromtable || ';' as text,
s.view_to_be_created, (s.noofcols * 2) + 3 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
where o.rnk = s.noofcols
order by view_to_be_created, rnk;
開始データで生成されるもの:
TEXT V RNK
------------------------------------------------------------ - ----------
CREATE OR REPLACE VIEW A AS SELECT A 1
KEYVALUE, A 2
NUM1 AS KEY1, A 3
NUM1 AS NO1, A 4
NUM1||'|'||NUM2 AS KEY2, A 5
NUM2 AS NO2, A 6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3 A 7
NUM3 AS NO3 A 8
FROM A1; A 9
CREATE OR REPLACE VIEW B AS SELECT B 1
KEYVALUE, B 2
NUM1 AS KEY1, B 3
NUM1 AS NO1, B 4
NUM1||'|'||NUM2 AS KEY2, B 5
NUM2 AS NO2, B 6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3, B 7
NUM3 AS NO3, B 8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4 B 9
NUM4 AS NO4 B 10
FROM B1; B 11
CREATE OR REPLACE VIEW C AS SELECT C 1
KEYVALUE, C 2
NUM1 AS KEY1, C 3
NUM1 AS NO1, C 4
NUM1||'|'||NUM2 AS KEY2, C 5
NUM2 AS NO2, C 6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3, C 7
NUM3 AS NO3, C 8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4, C 9
NUM4 AS NO4, C 10
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5 AS KEY5 C 11
NUM5 AS NO5 C 12
FROM C1; C 13
seeding_table
間の結合で別のCTEを使用して、少し変更することができます。 およびordercols_forview_cte
そしてそれを組合に使う。再帰CTE(Oracle 11gから)からパスを取得することもできます:
with r (keyvalue, fromtable, colsavailable, rnk, path) as (
select keyvalue, fromtable, colsavailable, rnk, colsavailable
from ordercols_forview
where rnk = 1
union all
select ocfv.keyvalue, ocfv.fromtable, ocfv.colsavailable, ocfv.rnk,
r.path || q'[||'|'||]' || ocfv.colsavailable
from r
join ordercols_forview ocfv
on ocfv.keyvalue = r.keyvalue
and ocfv.fromtable = r.fromtable
and ocfv.rnk = r.rnk + 1
)
select * from r;
そして、代わりにそれを使用できます。これにより、上記のように、その再帰CTEと別のCTEのシードテーブルが結合されますが、階層クエリCTEを再帰クエリCTEに置き換えるだけです。
with r (keyvalue, fromtable, colsavailable, rnk, path) as (
select keyvalue, fromtable, colsavailable, rnk, colsavailable
from ordercols_forview
where rnk = 1
union all
select ocfv.keyvalue, ocfv.fromtable, ocfv.colsavailable, ocfv.rnk,
r.path || q'[||'|'||]' || ocfv.colsavailable
from r
join ordercols_forview ocfv
on ocfv.keyvalue = r.keyvalue
and ocfv.fromtable = r.fromtable
and ocfv.rnk = r.rnk + 1
),
combined_cte as (
select s.keyvalue, s.view_to_be_created, s.noofcols,
r.fromtable, r.colsavailable, r.rnk, r.path
from seeding_table s
join r on r.keyvalue = s.keyvalue
)
select 'CREATE OR REPLACE VIEW ' || c.view_to_be_created || ' AS SELECT ' as text,
c.view_to_be_created, c.rnk
from combined_cte c
where c.rnk = 1
union all
select 'KEYVALUE,' as text,
c.view_to_be_created, c.rnk + 1 as rnk
from combined_cte c
where c.rnk = 1
union all
select c.path || ' AS KEY' || c.rnk
|| case when c.rnk < c.noofcols then ',' end,
c.view_to_be_created, (c.rnk * 2) + 1 as rnk
from combined_cte c
union all
select c.colsavailable || ' AS NO' || c.rnk
|| case when c.rnk < c.noofcols then ',' end as text,
c.view_to_be_created, (c.rnk * 2) + 2 as rnk
from combined_cte c
union all
select 'FROM ' || c.fromtable || ';' as text,
c.view_to_be_created, (c.noofcols * 2) + 3 as rnk
from combined_cte c
where c.rnk = c.noofcols
order by view_to_be_created, rnk;
同じ結果が得られます:
TEXT V RNK
------------------------------------------------------------ - ----------
CREATE OR REPLACE VIEW A AS SELECT A 1
KEYVALUE, A 2
NUM1 AS KEY1, A 3
NUM1 AS NO1, A 4
NUM1||'|'||NUM2 AS KEY2, A 5
NUM2 AS NO2, A 6
...
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3, C 7
NUM3 AS NO3, C 8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4, C 9
NUM4 AS NO4, C 10
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5 AS KEY5 C 11
NUM5 AS NO5 C 12
FROM C1; C 13