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

Splitting every row of varchar column and create new row for every split part

我有一个名为 "Table" 的 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);

我想用分号 (;) 拆分此属性,并为每个历史部分创建一个新行。因此,对于上面 code/example 中的行,它应该创建 7 行。我已经通过下面的代码设法在一行中执行此操作。问题是我想对 table 中的每一行都这样做。这里出现了一个问题:当我删除 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

如果要对多行使用 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;

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

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.