拆分 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.
我有一个名为 "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.