2017-03-19 33 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