Reputation: 783
I have some strings within a column of a table like asdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd
. I am wondering how may I extract the largest number within such a string in each row. For example, here the largest number is 188
(out of 188
, 98
and 78
).
Since the numbers I'm interested in are always right after AB
, I was thinking about using regexp_substr
. Unfortunately, I'm not sure how to have it output multiple rows so that I can use max
clause. PLSQL language would be great as well. Please show me a simple example if you have an idea. Thank you in advance!
Upvotes: 0
Views: 855
Reputation: 142705
Alternatively (to Alex' answer), if there are multiple rows:
SQL> with your_table (id, str) as (
2 select 1, 'sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd' from dual
3 union all select 2, '123abc456abc78d9' from dual
4 )
5 select id, max(to_number(regexp_substr(str, '\d+', 1, column_value))) max_num
6 from your_table,
7 table(cast(multiset(select level from dual
8 connect by level <= regexp_count(str, '\d+')
9 ) as sys.odcinumberlist))
10 group by id;
ID MAX_NUM
---------- ----------
1 188
2 456
SQL>
Upvotes: 1
Reputation: 191265
You could tokenize the string into all its number components, and then find the maximum:
select max(to_number(
regexp_substr('sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd', '(\d+)', 1, level))
) as max_value
from dual
connect by regexp_substr('sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd', '(\d+)', 1, level)
is not null;
MAX_VALUE
----------
188
or
select max(to_number(
regexp_substr('sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd', '(\d+)', 1, level, null, 1))
) as max_value
from dual
connect by level <= regexp_count('sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd', '\d+');
MAX_VALUE
----------
188
If you need to get values from multiple rows you need the connect-by to match the IDs, and also need to include a reference to a non-deterministic function to prevent looping; with two values in a CTE:
with your_table (id, str) as (
select 1, 'sdfAB98:(hjkl,)AB188(uiop)uuuAB78:jknd' from dual
union all select 2, '123abc456abc78d9' from dual
)
select id, max(to_number(regexp_substr(str, '(\d+)', 1, level, null, 1))) as max_value
from your_table
connect by prior id = id
and prior dbms_random.value is not null
and level <= regexp_count(str, '\d+')
group by id;
ID MAX_VALUE
---------- ----------
1 188
2 456
Upvotes: 3