【发布时间】:2018-11-28 11:19:46
【问题描述】:
如何使用 SQL 或 PL/SQL 从下面的字符串中提取所有数字?
[ 6d (1.5h; 31h)] x (5 到 7)
[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 到 5)
【问题讨论】:
-
你期待什么结果?
如何使用 SQL 或 PL/SQL 从下面的字符串中提取所有数字?
[ 6d (1.5h; 31h)] x (5 到 7)
[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 到 5)
【问题讨论】:
您可以使用正则表达式和相关的分层查询来获取值:
Oracle 设置:
CREATE TABLE table_name ( id, value ) AS
SELECT 1, '[ 6d (1.5h; 31h)] x (5 to 7)' FROM DUAL UNION ALL
SELECT 2, '[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 to 5)' FROM DUAL;
查询:
SELECT id, COLUMN_VALUE
FROM table_name t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.value, '\d+\.?\d*', 1, LEVEL )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.value, '\d+\.?\d*' )
) AS SYS.ODCINUMBERLIST
)
) n;
结果:
ID COLUMN_VALUE
--- ------------
1 6
1 1.5
1 31
1 5
1 7
2 1
2 8
2 24
2 48.5
2 72
2 96
2 1
2 5
查询 2:
SELECT REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 1 ) AS days,
REGEXP_REPLACE(
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 2 ),
'[^0-9.;]'
)AS hours,
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 3 ) AS x_from,
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 4 ) AS x_to
FROM table_name t;
结果:
DAYS HOURS X_FROM X_TO
---- --------------- ------ ----
6 1.5;31 5 7
1 8;24;48.5;72;96 1 5
【讨论】:
您可以通过 regexp_replace 的贡献导出由分隔符(在这种情况下为管道)分隔的所有数字,如下所示:
select regexp_replace('[ 6d (1.5h; 31h)] x (5 to 7)','[^0-9.]+','|') str from dual union all
select regexp_replace('[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 to 5)','[^0-9.]+','|') from dual;
STR
------------------
|6|1.5|31|5|7|
|1|8|24|48.5|72|96|1|5|
【讨论】: