2011-09-20 106 views
2

我有表:的Oracle 11g拆分文本列行

ID |Values 
-----+-------------------------------- 
1 |AB,AD 
2 |AG, ... ,BD 
3 |AV 

我怎樣才能把它轉換爲:

ID |Value 
-----+------ 
1 |AB 
1 |AD 
2 |AG 
... |... 
2 |BD 
3 |AV 
+0

我使用一個select語句 – spiaire

+0

可怕的DB設計做到這一點,存儲分隔字符串中的值。建議您的應用程序設計者(或DBA)在插入數據庫之前分割字符串。 – Ollie

+0

@Ollie和downvoters:這並不罕見。這實際上是一個很好的問題 –

回答

6

使用內置的XML功能,你可以做這樣的:

with sample_data as 
(
select 1 id, 'AB,AD' vals from dual union all 
select 2, 'AG,AK,AJ,BA,BD' from dual union all 
select 3, 'AV' from dual 
) 
select id, cast(t.column_value.extract('//text()') as varchar2(10)) val 
    from sample_data, 
    table(xmlsequence(xmltype(
    '<x><x>' || replace(vals, ',', '</x><x>') || '</x></x>' 
).extract('//x/*'))) t; 

結果:

ID VAL 
--- ----- 
1 AB 
1 AD 
2 AG 
2 AK 
2 AJ 
2 BA 
2 BD 
3 AV 
+0

+1,XML功能非常適合這樣做。 – Ollie

2

使用遞歸公用表表達式,相同的查詢看起來是這樣的:

with sample_data as 
(
    select 1 id, 'AB,AD' vals from dual union all 
    select 2, 'AG,AK,AJ,BA,BD' from dual union all 
    select 3, 'AV' from dual 
), 
split_first(id, val, rem) as 
(
    select id, 
    coalesce(substr(vals, 1, instr(vals, ',') - 1), vals) val, 
    case when instr(vals, ',') > 0 then substr(vals, instr(vals, ',') + 1) end rem 
    from sample_data 
    union all 
    select id, 
    coalesce(substr(rem, 1, instr(rem, ',') - 1), rem) val, 
    case when instr(rem, ',') > 0 then substr(rem, instr(rem, ',') + 1) end rem 
    from split_first 
    where rem is not null 
) 
select id, val from split_first 
order by id; 

或者稍微不同的方法:

with sample_data as 
(
    select 1 id, 'AB,AD' vals from dual union all 
    select 2, 'AG,AK,AJ,BA,BD' from dual union all 
    select 3, 'AV' from dual 
), 
pos(id, seq, vals, sta, stp) as 
(
    select id, 1, vals, 1, instr(vals, ',') from sample_data 
    union all 
    select id, seq + 1, vals, stp + 1, instr(vals, ',', stp + 1) from pos 
    where stp > 0 
) 
select id, substr(vals, sta, case when stp > 0 then stp - sta else length(vals) end) from pos 
order by id, seq; 
+0

哪種解決方案更高效? – spiaire

+0

I/O明智,它應該沒有任何區別,因爲相同的行被處理。 CPU聰明的第二個查詢可能更有效,因爲它使用較少的字符串操作。 – Codo