how fetch specific values from String in db2 query - sql

my table has value like this "lowValue=100,upperValue=200".
i tried substr and trim function to trim lowValue= and upperValue= text. nothing worked for me
Select contantName,constantValue from Test where contantName="test1";
-------------------------------------------------
contantName constantValue
-------------------------------------------------
test1 lowValue=100,upperValue=200
-------------------------------------------------
How to get only lowValue and highvalue in select query.
i want output to fetch only numbers from the constant value 100 and 200.

select contantName, REPLACE(REPLACE(constantValue,'lowValue=',''), 'upperValue=','') from Test where contantName="test1";

This would be a solution for the sample shown
WITH test (constantValue) AS (
SELECT 'lowValue=1000,upperValue=20000' AS constantValue FROM SYSIBM.SYSDUMMY1
)
SELECT constantValue
, substr(constantValue, posstr(constantValue, 'lowValue=') + 9 , posstr(constantValue, ',') - (posstr(constantValue, '=')+1)) AS lowvalue
, substr(constantValue, posstr(constantValue, 'upperValue=') + 11 , length(constantValue) - (posstr(constantValue, 'upperValue=')+10)) AS uppervalue
FROM test

REGEXP_SUBSTR can do it
SELECT
REGEXP_SUBSTR(value, '\blowValue=(\d+)', 1, 1, 'c', 1) as "lowValue",
REGEXP_SUBSTR(value, '\bupperValue=(\d+)', 1, 1, 'c', 1) as "upperValue"
FROM (VALUES 'lowValue=54321,upperValue=123') AS base (value)

Related

How do I get substring after a character when the occurance of the character keeps changing

Example
123\.456.578.910.ABC
123\.456.578.910
Expected result
123\.456.578
123\.456.578
For the both the inputs I should get only the first 3
I tried the regexp and substring and instr but I’m not getting the results
We can use REGEXP_SUBSTR here with a capture group:
SELECT REGEXP_SUBSTR(col, '^(\d+(\.\d+)*)', 1, 1, NULL, 1)
FROM yourTable;
Demo
Traditional, substr + instr combination is another option:
Sample data:
SQL> with test (col) as
2 (select '123\.456.578.910.ABC' from dual union all
3 select '123\.456.578.910' from dual
4 )
Query begins here:
5 select col,
6 substr(col, 1, instr(col, '.', 1, 3) - 1) result
7 from test;
COL RESULT
-------------------- --------------------
123\.456.578.910.ABC 123\.456.578
123\.456.578.910 123\.456.578
SQL>
If you value will always have at least 3 . characters then you can use:
SELECT value,
SUBSTR(value, 1, INSTR(value, '.', 1, 3) - 1) AS expected
FROM table_name;
If it may have fewer and you want the entire string in those cases then:
SELECT value,
CASE INSTR(value, '.', 1, 3)
WHEN 0
THEN value
ELSE SUBSTR(value, 1, INSTR(value, '.', 1, 3) - 1)
END AS expected
FROM table_name;
Which, for your sample data:
CREATE TABLE table_name (value) AS
SELECT '123\.456.578.910.ABC' FROM DUAL UNION ALL
SELECT '123\.456.578.910' FROM DUAL;
Both outputs:
VALUE
EXPECTED
123.456.578.910.ABC
123.456.578
123.456.578.910
123.456.578
db<>fiddle here

Substring from underscore and onwards in Oracle

I have a string with under score and some characters. I need to apply substring and get values to the left excluding underscore. So I applied below formula and its working correctly for those strings which have underscore (_). But for strings without (_) it is bringing NULL. Any suggestions how this can be handled in the substring itself.
Ex: ABC_BASL ---> Works correctly; ABC ---> gives null
My formula as below -
select SUBSTR('ABC_BAS',1,INSTR('ABC_BAS','_')-1) from dual;
ABC
select SUBSTR('ABC',1,INSTR('ABC','_')-1) from dual;
(NULL)
You could use a CASE expression to first check for an underscore:
WITH yourTable AS (
SELECT 'ABC_BAS' AS col FROM dual UNION ALL
SELECT 'ABC' FROM dual
)
SELECT
CASE WHEN col LIKE '%\_%' ESCAPE '\'
THEN SUBSTR(col, 1, INSTR(col, '_') - 1)
ELSE col END AS col_out
FROM yourTable;
Use regular expression matching:
SELECT REGEXP_SUBSTR('ABC_BAS', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;
returns 'ABC', and
SELECT REGEXP_SUBSTR('ABC', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;
also returns 'ABC'.
db<>fiddle here
EDIT
The above gives correct results, but I missed the easiest possible regular expression to do the job:
SELECT REGEXP_SUBSTR('ABC_BAS', '[^_]*') FROM DUAL;
returns 'ABC', as does
SELECT REGEXP_SUBSTR('ABC', '[^_]*') FROM DUAL;
db<>fiddle here
Yet another approach is to use the DECODE in the length parameter of the substr as follows:
substr(str,
1,
decode(instr(str,'_'), 0, lenght(str), instr(str,'_') - 1)
)
You seem to want everything up to the first '_'. If so, one method usesregexp_replace():
select regexp_replace(str, '(^[^_]+)_.*$', '\1')
from (select 'ABC' as str from dual union all
select 'ABC_BAS' from dual
) s
A simpler method is:
select regexp_substr(str, '^[^_]+')
from (select 'ABC' as str from dual union all
select 'ABC_BAS' from dual
) s
Here is a db<>fiddle.
I'd use
regexp_replace(text,'_.*')
or if performance was a concern,
substr(text, 1, instr(text||'_', '_') -1)
For example,
with demo(text) as
( select column_value
from table(sys.dbms_debug_vc2coll('ABC', 'ABC_DEF', 'ABC_DEF_GHI')) )
select text
, regexp_replace(text,'_.*')
, substr(text, 1, instr(text||'_', '_') -1)
from demo;
TEXT REGEXP_REPLACE(TEXT,'_.*') SUBSTR(TEXT,1,INSTR(TEXT||'_','_')-1)
------------ --------------------------- -------------------------------------
ABC ABC ABC
ABC_DEF ABC ABC
ABC_DEF_GHI ABC ABC
Ok i think i got it. Add nvl to the substring and insert the condition as below -
select nvl(substr('ABC',1,instr('F4001Z','_')-1),'ABC') from dual;

Substring from string oracle

I have strings : 'A-20-1-1', 'A-10-10', 'A-10-11-1'
And result from substringing:
'A-20-1-1', 'A-10-10', 'A-10-11-1'
1 10 11
Code won't works fine:
Select Substr(string, instr(string,'-',1,2)+1, instr(string, '-',1,2)-1)
From dual;
At the beginning I find second '-', than next one if exists. If not I get string length.
create table a(b varchar2(20));
insert into a values('A-20-1-1');
insert into a values('A-10-10');
insert into a values('A-10-11-1');
Select
b,
substr(b,instr(b,'-',1,2)+1,decode(instr(b,'-',1,3),0,length(b)-instr(b,'-',1,2),instr(b,'-',1,3)-instr(b,'-',1,2)-1)) z
from a;
gives us what you need:
A-20-1-1 1
A-10-10 10
A-10-11-1 11
At first I find the second - sign position, and then get a substring of the value from this position to the rest of the value. Then I exclude the part of the string from previous step if the string has the - sign. Like this:
with t(d) as (
select 'A-20-1-1' from dual union all
select 'A-10-10-4' from dual union all
select 'A-10-11-1' from dual
)
select REPLACE(SUBSTR(d, INSTR(d, '-', 1, 2) + 1), SUBSTR(d, INSTR(d, '-', 1, 3))) from t
RES
---
1
10
11

Reg Expression in oracle?

I have a string like this '102/103/104/106'
Now if i pass 102 as input then output should be the next field that is 103. if 103 then output should be 104 and if 106 then output should be null(as for last field I don't have any further expression). I can do this using procedure by splitting the string into arrays and comparing. But can I do this through sql statement something like this
select '102/103/104/106' from dual where [expression 102 or 103].
Thanks!!
You can do it in pure SQL with something like this:
--convert your string into rows
with vals as (
select
substr('102/103/104/106',
instr('102/103/104/106', '/', 1, level)-3,
3
) col,
level lvl
from dual
connect by level <= length('102/103/104/106')-length(replace('102/103/104/106', '/'))+1
)
select *
from (
select col,
lead(col) over (order by lvl) next_val -- find the next value in the list
from vals
)
where col = :val;
Basically, convert your string into rows by parsing it. Then use the analytic lead to find the "next" value.
-- p_whole_string = '102/103/104/106'
-- p_prev = '102'
select
regexp_substr(p_whole_string, '(^|/)' || p_prev || '/([^/]+)', 1, 1, null, 2)
as next
from dual;
Added NVL to return last value if 106 is entered:
SELECT NVL(REGEXP_SUBSTR('102/103/104/106', '(^|/)' || '106' || '/([^/]+)', 1, 1, null, 2), REGEXP_SUBSTR('102/103/104/106', '[^/]+$')) as nxt
FROM dual
/
works for Oracle form 10 up.
SELECT
REGEXP_SUBSTR(
REGEXP_SUBSTR('102/103/104/106', '(^|/)102/[^/]+'), -- returns 102/103
'[^/]+',1,2) val -- takes second part
FROM DUAL;
with parameters looks like this:
-- p_string_to_search = '102/103/104/106'
-- p_string_to_match = '102'
SELECT
REGEXP_SUBSTR(
REGEXP_SUBSTR(p_string_to_search, '(^|/)' || p_string_to_match ||'/[^/]+'), -- returns 102/103
'[^/]+',1,2) val -- takes second part
FROM DUAL;

How to fetch 4 characters from a string in oracle?

By using following query i am able to fetch a particular string.Now this output string contains alphanumeric characters.e.g.abcd123,pqrs542356.
Now i want to fetch only first 4 characters of this string which will be always alpha bates.
Query::
(SELECT SUBSTR(in_msg, INSTR( in_msg,'?', 1, 10 )+ 1, INSTR(in_msg,'?', 1, 11 ) - INSTR( in_msg,'?', 1, 10 )- 1)
FROM emp_message
WHERE emp_no IN (SELECT emp_no
FROM main_table
WHERE name like '%abcd%')
This query returns output as e.g.abcd1234,pqrs145423.
Again i want to fetch only first 4 characters from this query output.
Can somebody help me in this.
You can use substr (like you already do):
SUBSTR(value, 1, 4)
Here it is:
SUBSTR(field, 0, 4)
select substr(x, 1, 4) from
( select x from ..... )