2017-03-19 59 views
0

我有一個表格,其數據格式如下。將CSV列拆分成行並在列之間匹配

PK COL1   COl2 
r1 abc,abd  zyx,xyz 
r2 bde,cse,bxo ajy,bix,rxo 
r3 zde,cse,bxo ajy,xir,sxo 

在COL1映射條目的序列COL2即在R 1,ABC映射到ZYX,ABD映射到xyz的。不要問我是誰想出了這個想法:)

所以,現在我有一個要求將其轉換爲常規的關係結構。

PK COL1 COL2 
r1 abc zyx 
r1 abd xyz 
r2 bde ajy 
r2 cse bix 
r2 bxo rxo 
r3 zde ajy 
r3 cse xir 
r3 bxo sxo 

我看了其他可用於將CSV列轉換爲行的示例。所有這些工作正常單CSV列。但是有2個CSV列,a)我如何才能使其工作,並且b)還要確保映射序列不受干擾。有什麼建議麼?

感謝 askids

+0

忘了提。我們在oracle 11g上。單個值的3個字節長度不固定。它可以在行與行之間以及col1與col2之間變化。 – askids

回答

1
with 
    test_data (pk, col1, col2) as ( 
     select 'r1', 'abc,abd' , 'zyx,xyz'  from dual union all 
     select 'r2', 'bde,cse,bxo', 'ajy,bix,rxo' from dual union all 
     select 'r3', 'zde,cse,bxo', 'ajy,xir,sxo' from dual 
    ) 
-- end of test data, SQL query begins below this line 
select pk, 
     regexp_substr(col1, '([^,]*)(,|$)', 1, level, null, 1) as col1, 
     regexp_substr(col2, '([^,]*)(,|$)', 1, level, null, 1) as col2 
from test_data 
connect by level <= length(col1) - length(replace(col1, ',')) + 1 
     and prior pk = pk 
     and prior sys_guid() is not null 
; 

PK COL1 COL2 
-- ---- ---- 
r1 abc zyx 
r1 abd xyz 
r2 bde ajy 
r2 cse bix 
r2 bxo rxo 
r3 zde ajy 
r3 cse xir 
r3 bxo sxo 
0

請注意,如果COL1 COL2或可包含逗號之間的空值,則需要更復雜的正則表達式:

SQL> select 
    t.pk, 
    regexp_substr(t.col1, '[^,]+',1,ordno.n) as col1, 
    regexp_substr(t.col2, '[^,]+',1,ordno.n) as col2 
from (
    select 'r1' pk, 'abc,abd' col1, 'zyx,xyz' col2 from dual union all 
    select 'r2' pk, 'bde,cse,bxo' col1, 'ajy,bix,rxo' col2 from dual union all 
    select 'r3' pk, 'zde,cse,bxo' col1, 'ajy,xir,sxo' col2 from dual 
) t 
    join (select level n from dual connect by level <= 1000) ordno 
    on ordno.n <= regexp_count(t.col1, '[^,]+') 
order by t.pk; 

PK COL1  COL2  
-- ----------- ----------- 
r1 abc   zyx   
r1 abd   xyz   
r2 cse   bix   
r2 bxo   rxo   
r2 bde   ajy   
r3 zde   ajy   
r3 bxo   sxo   
r3 cse   xir   

8 rows selected