原始需求:
有這樣的表:tb和pk兩列
PK是將表的多個主鍵用“|”進行分隔,我想把它變成多行
如
fundamentals_asia1_af_out |
ID_BB_GLOBAL|BC_DT|BC_EQY_DVD_ADJUST_FACT|BC_EQY_DVD_ADJ_FUND_OPER|BC_EQY_DVD_ADJ_FUND_FLAG |
變成:
fundamentals_asia1_af_out |
ID_BB_GLOBAL |
fundamentals_asia1_af_out |
BC_DT |
fundamentals_asia1_af_out |
BC_EQY_DVD_ADJUST_FACT |
fundamentals_asia1_af_out |
BC_EQY_DVD_ADJ_FUND_OPER |
fundamentals_asia1_af_out |
BC_EQY_DVD_ADJ_FUND_FLAG |
方案一
with t_n as( select rownum as N from dual connect by rownum<=200 ) ,cte as ( select 'equity_asia1_dif' tb,'ID_BB_GLOBAL|RC' pk from dual union all select 'fundamentals_asia1_af_out','ID_BB_GLOBAL|BC_DT|BC_EQY_DVD_ADJUST_FACT|BC_EQY_DVD_ADJ_FUND_OPER|BC_EQY_DVD_ADJ_FUND_FLAG' from dual union all select 'fundamentals_asia1_bs_out','ID_BB_GLOBAL|FISCAL_YEAR_PERIOD|FILING_STATUS|EQY_CONSOLIDATED|ACCOUNTING_STANDARD' from dual ),res as ( select a.*,b.*,nvl(lag(b.n) over(partition by a.tb order by b.n),0) as head from cte a inner join t_n b on length(a.pk||'|')>=b.n where substr(a.pk||'|',b.n,1)='|' ) select tb,substr(pk,head+1,n-head-1),pk from res order by tb,n;
用到的知識點:
- l 公用表表達式:with xxx as ()
- l Connect by : 我這里用它來簡單的構建了一個1-50的序號。可以百度它的高級用法
- l Lag() over():開窗函數
- l 利用序號表進行拆分(實際是個技巧,它還有很多的妙用)
方案二(正則)
with a as ( select 'equity_asia1_dif' tb,'ID_BB_GLOBAL|RC' pk from dual union all select 'fundamentals_asia1_af_out','ID_BB_GLOBAL|BC_DT|BC_EQY_DVD_ADJUST_FACT|BC_EQY_DVD_ADJ_FUND_OPER|BC_EQY_DVD_ADJ_FUND_FLAG' from dual union all select 'fundamentals_asia1_bs_out','ID_BB_GLOBAL|FISCAL_YEAR_PERIOD|FILING_STATUS|EQY_CONSOLIDATED|ACCOUNTING_STANDARD' from dual ) select t1.tb,regexp_substr(pk,'[^|]+',1,t2.lv) pk from a t1, (select level lv from (select max(regexp_count(pk,'[^|]+',1))+1 ct from a) b connect by level<b.ct) t2 where regexp_substr(pk,'[^|]+',1,t2.lv) is not null order by 1,t2.lv