拆分varchar列的每一行,并为每个拆分部分创建新行

时间:2018-11-27 12:51:34

标签: sql oracle split common-table-expression

我有一个名为“ Table”的表和一个名为“ History”的属性。此历史记录属性的值如下:

   1 Finished (30-05-2018);
   2 InProgress (25-05-2018); Rejected(26-05-2018); InProgress (28-05-2018); Finished (30-05-2018);
   3 InProgress (25-05-2018); Finished (30-05-2018);

我想用分号(;)分割此属性,并为每个历史记录部分创建一个新行。因此,对于上面的代码/示例中的行,应创建7行。我已经通过下面的代码成功完成了这一行。问题是我想对表中的每一行执行此操作。这里发生一个问题:当我在WITH中删除WHERE条件时,我将获得许多结果行以及许多NULL值。我究竟做错了什么?

WITH DATA AS
   ( SELECT "WorkID" w,"History" his FROM Table
   where "WorkID" = 75671
   )
   SELECT w, trim(regexp_substr(his, '[^;]+', 1, LEVEL)) his
   FROM DATA
   CONNECT BY regexp_substr(his , '[^;]+', 1, LEVEL) IS NOT NULL

2 个答案:

答案 0 :(得分:1)

这是一个完整的工作示例,其中正则表达式查找分号的定界符,后跟空格或行尾:

SQL> WITH Tbl(WorkID, History) AS(
     select 1, 'Finished (30-05-2018);' from dual union all
     select 2, 'InProgress (25-05-2018); Rejected(26-05-2018); InProgress (28-05-2018); Finished (30-05-2018);' from dual union all
     select 3, 'InProgress (25-05-2018); Finished (30-05-2018);' from dual
   )
   select WorkID, regexp_substr(History, '(.*?)(; |;$)', 1, level, NULL, 1) history
   from Tbl
   connect by regexp_substr(History, '(.*?)(; |;$)', 1, level) is not null
   and prior WorkID = WorkID
   and prior sys_guid() is not null;

    WORKID HISTORY
---------- -------------------------
         1 Finished (30-05-2018)
         2 InProgress (25-05-2018)
         2 Rejected(26-05-2018)
         2 InProgress (28-05-2018)
         2 Finished (30-05-2018)
         3 InProgress (25-05-2018)
         3 Finished (30-05-2018)

7 rows selected.

答案 1 :(得分:0)

如果您想对多行使用connect by来将一列拆分为多行,则需要做一些额外的事情-一种告诉Oracle遍历同一行的方法,并进行检查确保知道要使用的前一行。

这意味着您的查询将变为:

select "WorkID" w,
       "History" his
from table
connect by prior "WorkID" = "WorkID" -- I'm assuming that "WorkID" uniquely identifies a row; if not, add in the additional columns that identify a row
and regexp_substr("History", '[^;]+', 1, level) is not null
and prior sys_guid() is not null;