我有一个带有varchar2(5000 char)列的表,其中包含几个句子。在这样的句子中的某个地方显示了一个数字,然后是另一个数字。我想选择这些数字并将它们除。不确定如何在sqlplus oracle 11g中执行此操作。
我认为我应该使用类似SUBSTR, REGEXP_SUBSTR, INSTR
的函数。不确定哪个最适合这份工作。
列如下:
blah bahwl balwo hxkswl blahxhsh alshbhe NUM 40003.26 in 4 pieces. etc
bwh bahwl bafado hxkswl alshbhe NUM 6006.16 in 9 pieces. etc
badh baadfl balwo hxkswl blahxhsh alshbhe NUM 200 in 30 pieces. etc
bfda bdafl hxkswl NUM 33 in 4 pieces. etc
blcfh bfdwl bfdlwo alshbhe NUM 54545.01 in 700 pieces. etc
所以我想直接在NUM之后搜索并选择一个数字,然后在“ in”和“ pieces”之间选择一个数字,然后将这些数字相除。
select .... 40003.26 / 4
select .... 6006,16 / 9
select .... 200 / 30
等
任何帮助表示感谢
答案 0 :(得分:1)
您可以按以下方式使用regexp_substr
/ regexp_replace
和l
,rtrim
with t1 as
(select 'blah bahwl balwo hxkswl blahxhsh alshbhe NUM 40003.26 in 4 pieces. etc
bwh bahwl bafado hxkswl alshbhe NUM 6006.16 in 9 pieces. etc
badh baadfl balwo hxkswl blahxhsh alshbhe NUM 200 in 30 pieces. etc
bfda bdafl hxkswl NUM 33 in 4 pieces. etc
blcfh bfdwl bfdlwo alshbhe NUM 54545.01 in 700 pieces. etc' as str
from dual),
t2 as
(select regexp_substr(str, '(.*)pieces.*', 1, level) as str
from t1
cross join dual
connect by level <= regexp_count(str, 'pieces')),
t3 as
(select str,
regexp_replace(str, '[^0-9]in[^0-9]', '/') str1,
regexp_substr(str, '[^0-9]*') str2,
regexp_substr(str, '[^0-9]*$') str3
from t2)
select rtrim(ltrim(str1, str2), str3) as "Result String" from t3
Result String
-------------
40003.26/4
6006.16/9
200/30
33/4
54545.01/700
答案 1 :(得分:0)
此选项选择输入字符串的NUM blabla
部分,与其中出现NUM的次数相同(这就是INTER
CTE所做的事情)。最后的SELECT
(向前13行)提取数值并将其除以产生结果。
SQL> with test (col) as
2 (select 'blah bahwl balwo hxkswl blahxhsh alshbhe NUM 40003.26 in 4 pieces. etc
3 bwh bahwl bafado hxkswl alshbhe NUM 6006.16 in 9 pieces. etc
4 badh baadfl balwo hxkswl blahxhsh alshbhe NUM 200 in 30 pieces. etc
5 bfda bdafl hxkswl NUM 33 in 4 pieces. etc
6 blcfh bfdwl bfdlwo alshbhe NUM 54545.01 in 700 pieces. etc' from dual
7 ),
8 inter as
9 (select regexp_substr(col, 'NUM \d+(\.\d+)? in \d+', 1, level) res
10 from test
11 connect by level <= regexp_count(col, 'NUM')
12 )
13 select res,
14 regexp_substr(res, '\d+(\.\d+)?') c1,
15 regexp_substr(res, '\d+$') c2,
16 --
17 round(to_number(regexp_substr(res, '\d+(\.\d+)?'), '99999999D99',
18 ' NLS_NUMERIC_CHARACTERS = ''.,''') /
19 to_number(regexp_substr(res, '\d+$')), 2) result
20 from inter;
RES C1 C2 RESULT
-------------------- ---------- ---------- ----------
NUM 40003.26 in 4 40003.26 4 10000,82
NUM 6006.16 in 9 6006.16 9 667,35
NUM 200 in 30 200 30 6,67
NUM 33 in 4 33 4 8,25
NUM 54545.01 in 700 54545.01 700 77,92
SQL>
答案 2 :(得分:0)
如果您可以保证,该全部(我的意思是全部)行将包含您所描述的片段,例如:{{ 1}},其中NUM ..... in ..... pieces
是两个数字,第二个数字不为0(因此我们不除以0),那么您可以使用XMLQuery来实现,就像这样:
.....
即使您不熟悉XMLQuery,也不难理解在这种特殊情况下XMLQuery是如何工作的。您可能需要单独选择REGEXP_REPLACE的结果,以查看XMLQuery的实际输入。
但是,此解决方案将阻塞更大的数据集中的任何,如下所示,它们是with
test_data as (
select 1 id, 'blah bahwl NUM 40003.26 in 4 pieces. etc' str from dual union all
select 2 , 'bwh balshbh NUM 6006.16 in 9 pieces. etc' from dual union all
select 3 , 'badh sh alshbh NUM 200 in 30 pieces. etc' from dual union all
select 4 , 'bfda bdafl hxksw NUM 33 in 4 pieces. etc' from dual union all
select 5 , 'bl lshbh NUM 54545.01 in 700 pieces. etc' from dual
)
select id,
xmlquery(regexp_replace(str, '^.*?NUM(.*?)in(.*?)pieces.*$', '\1 div \2')
returning content).getNumberVal() as division_result
from test_data
;
ID DIVISION_RESULT
----- ---------------
1 10000.815000
2 667.351111
3 6.666667
4 8.250000
5 77.921443
子句。
如果可能出现此类异常,则必须告诉我们应如何处理每个异常。请注意,WITH
根本没有所需的片段。 id = 6
缺少第二个数字; id = 7
的第二个数字等于0; id = 8
的文字应有数字。
这说明了为什么也许如果必须处理此类问题,您应该考虑添加两列,如果您的Oracle版本足够高,则可能要添加虚拟列,以仅容纳所需的数字-这样处理可能的异常会变得很多更轻松。显然,这也将使您的数据模型更接近于当前模型公然违反的“第一范式”。
id = 9