在Oracle中将列拆分为两个或更多列

时间:2016-07-28 11:40:46

标签: sql regex oracle

让我们说我的表看起来像这样:

-------------------------
| id | prop             |
-------------------------
| 1  | Jhon_Dhoe_21     |
-------------------------
| 2  | Tom_Dohn_23_MALE |
-------------------------
| 3  | Scot             |
-------------------------

属性将始终由" _"分隔。因此在SELECT之后,表格应如下所示:

--------------------------------------
| id | prop1 | prop2 | prop3 | prop4 |
--------------------------------------
| 1  |  Jhon | Dhoe  |  21   |  NULL |
--------------------------------------
| 2  |  Tom  | Dohn  |  23   |  MALE |
--------------------------------------
| 3  |  Scot | NULL  | NULL  |  NULL |
--------------------------------------

现在,如果我们知道可以拥有的最大属性数( n ),我想我们可以在 prop上创建 n 个正则表达式表达式  专栏。但是如果我们不知道也许我们必须首先找到具有大多数属性的

编辑:

我无法接受多行。

1 个答案:

答案 0 :(得分:2)

这是一个有趣的问题,所以我用这种方式解决了这个问题:

with
  tbl as (
    select 1 id, 'Jhon_Dhoe_21' prop from dual union all
    select 2 id, 'Tom_Dohn_23_MALE' prop from dual union all
    select 3 id, 'Scot' prop from dual
  ),
  maxrows as (select level rn from dual connect by level <= 100)
select id, regexp_substr(t.prop, '[^_]+', 1, mr.rn) prop_rn, rn, prop
from tbl t, maxrows mr
where mr.rn <= regexp_count(t.prop, '\_') + 1
order by id, rn

结果:

        ID PROP_RN                  RN PROP
---------- ---------------- ---------- ----------------
         1 Jhon                      1 Jhon_Dhoe_21
         1 Dhoe                      2 Jhon_Dhoe_21
         1 21                        3 Jhon_Dhoe_21
         2 Tom                       1 Tom_Dohn_23_MALE
         2 Dohn                      2 Tom_Dohn_23_MALE
         2 23                        3 Tom_Dohn_23_MALE
         2 MALE                      4 Tom_Dohn_23_MALE
         3 Scot                      1 Scot

8 rows selected

如果您知道(或确定)最大可能列,可以使用:

with
  tbl as (
    select 1 id, 'Jhon_Dhoe_21' prop from dual union all
    select 2 id, 'Tom_Dohn_23_MALE' prop from dual union all
    select 3 id, 'Scot' prop from dual
  ),
  maxrows as (select level rn from dual connect by level <= 100),
  tbl2 as (
    select id, regexp_substr(t.prop, '[^_]+', 1, mr.rn) prop_rn, rn, prop
    from tbl t, maxrows mr
    where mr.rn <= regexp_count(t.prop, '\_') + 1
    order by id, rn)
select *
from tbl2
pivot (
  max(prop_rn)
  for rn in (1,2,3,4,6,7,8,9,10)
)

结果:

        ID PROP             1                2                3                4                6                7                8                9                10
---------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ----------------
         1 Jhon_Dhoe_21     Jhon             Dhoe             21                                                                                                    
         3 Scot             Scot                                                                                                                                    
         2 Tom_Dohn_23_MALE Tom              Dohn             23               MALE                                                                                 

SQL> 

或使用xmltype:

with
  tbl as (
    select 1 id, 'Jhon_Dhoe_21' prop from dual union all
    select 2 id, 'Tom_Dohn_23_MALE' prop from dual union all
    select 3 id, 'Scot' prop from dual
  ),
  maxrows as (select level rn from dual connect by level <= 100),
  tbl2 as (
    select id, regexp_substr(t.prop, '[^_]+', 1, mr.rn) prop_rn, rn, prop
    from tbl t, maxrows mr
    where mr.rn <= regexp_count(t.prop, '\_') + 1
    order by id, rn)
select *
from tbl2
pivot xml (
  max(prop_rn) prp
  for rn in (any)
)