variable within a case expression oracle - sql

I have the following:
SELECT name,
listagg(
CASE length(TRIM(regexp_substr(lower(docs),
'process\s+explanation\s*:\s*(.*?)(\.\s*final activity|$)',
1, 1, 'i', 1)))
WHEN 0 THEN
lower(docs)
ELSE
regexp_substr(lower(docs),
'process\s+explanation\s*:\s*(.*?)(\.\s*final activity|$)',
1, 1, 'i', 1)
END, '. '
) AS final_doc
FROM my_table
GROUP BY
name
I don't want to repeat the regular expression: 'process\s+explanation\s*:\s*(.*?)(\.\s*final activity|$)'. I just want to define it once and use it. Or preferrably, I don't want this entire line duplicated: regexp_substr(lower(docs), 'process\s+explanation\s*:\s*(.*?)(\.\s*final activity|$)', 1, 1, 'i', 1). How can I do that? Version is 19c

You can use Common Table expression(WITH..AS) in such a way that
WITH t AS
(
SELECT m.*,
REGEXP_SUBSTR(docs,
'process\s+explanation\s*:\s*(.*?)(\.\s*final activity|$)',
1,
1,
'i',
1) AS rgs
FROM my_table m
)
SELECT name,
LISTAGG(CASE length(TRIM(rgs))
WHEN 0 THEN
lower(docs)
ELSE
rgs
END,
'. ') AS final_doc
FROM t
GROUP BY name

Related

Regex values after special character with empty values

I am struggle with regex to split spring into columns in Oracle database.
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '[^: ]+', 1, 4)) from dual;
I need to obtain 4th value from that string as a column value, sometimes values at position 2,3 are empty and my query doesn't work. I am trying to figure out what regex will work
You can use
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '([^: ]*)(:|$)', 1, 4, 'i', 1)) from dual;
Here, the ([^: ]*)(:|$) matches
([^: ]*) - Group 1: any zero or more chars other than : and space
(:|$) - Group 2, either : or end of string.
You do not need a (slower) regex for this task, use simple substr/instr functions:
with input_(val) as (
select '1:::9999' from dual
union all
select '1:2::' from dual
union all
select '1:2::3:5' from dual
)
, replaced as (
select input_.*, replace(val, ' ', '') as val_replaced
from input_
)
select
val,
substr(
val_replaced,
/*Locate the first occurrence of a colon and get a substring ...*/
instr(val_replaced, ':', 1, 3) + 1,
/*.. until the end, if the next colon is absent, or until the next colon*/
nvl(nullif(instr(val_replaced, ':', 1, 4), 0), length(val_replaced) + 1) - instr(val_replaced, ':', 1, 3) - 1
) as col
from replaced
VAL
COL
1:::9999
9999
1:2::
null
1:2::3:5
3
fiddle with performance difference.

I need to Update my row with english version

I have a column which includes rows like this : MER.Fiyatlandırma Müdür Yardımcısı.
SELECT name, SUBSTR(
name,
INSTR(name, '.', 1, 1),
INSTR(name, '.', 1, 2) + 1 - INSTR(name, '.', 1, 1)
) AS deneme
FROM HR_ALL_POSITIONS_F;
I used this code and my rows looks like .Fiyatlandırma Müdür Yardımcısı.
Also ı have an excel file which includes .Fiyatlandırma Müdür Yardımcısı. this row and english version.
I need to change .Fiyatlandırma Müdür Yardımcısı. this to Price Vice Manager.
How can ı do that.
UPDATE denememusa123
SET denememusa123.eklenecekkolon = (SELECT ENGLISHPOSITION FROM pozisyontanimlama)
WHERE (SELECT SUBSTR (name,
INSTR (name,
'.',
1,
1),
INSTR (name,
'.',
1,
2)
+ 1
- INSTR (name,
'.',
1,
1))
FROM HR_ALL_POSITIONS_F) = (Select TURKISHPOSITION FROM pozisyontanimlama);
(I tired this but it is not working.
ora-01427:single-row subquery returns more than one row )
Help Please.
You can use a MERGE statement:
MERGE INTO denememusa123 dst
USING (
WITH split_denememusa123 (rid, prefix, position, suffix) AS (
SELECT rowid AS rid,
SUBSTR(
eklenecekkolon,
1,
INSTR(eklenecekkolon, '.', 1, 1)
) AS prefix,
SUBSTR(
eklenecekkolon,
INSTR(eklenecekkolon, '.', 1, 1) + 1,
INSTR(eklenecekkolon, '.', 1, 2) - INSTR(eklenecekkolon, '.', 1, 1) - 1
) AS position,
SUBSTR(
eklenecekkolon,
INSTR(eklenecekkolon, '.', 1, 2)
) AS suffix
FROM denememusa123
WHERE INSTR(eklenecekkolon, '.', 1, 2) > 0
)
SELECT s.rid, s.prefix || p.englishposition || s.suffix AS position
FROM split_denememusa123 s
INNER JOIN pozisyontanimlama p
ON (p.turkishposition = s.position)
) src
ON (src.rid = dst.ROWID)
WHEN MATCHED THEN
UPDATE SET dst.eklenecekkolon = src.position;
Which, for the sample data:
CREATE TABLE denememusa123 (eklenecekkolon) AS
SELECT 'MER.Fiyatlandırma Müdür Yardımcısı.XYZ' FROM DUAL;
CREATE TABLE pozisyontanimlama (turkishposition, englishposition) AS
SELECT 'Fiyatlandırma Müdür Yardımcısı', 'Price Vice Manager' FROM DUAL
Then after the MERGE the table contains:
EKLENECEKKOLON
MER.Price Vice Manager.XYZ
fiddle

selected splitted value in oracle

I have two columns A, B in oracle where A value has values like that xx-target-xx
xx any data but target is exists
A
--------
xx-target-xx
xx-target
i neet to return only 'target' from text
i tired this
select TRIM(substr(A, 0, instr(A, '-') - 1)) from mytable
but the result returns xx not target
Use REGEXP_SUBSTR. You want the second string of any characters except the minus sign:
select a, regexp_substr(a, '[^-]+', 1, 2) from mytable;
Using INSTR and SUBSTR instead is a tad more complicated, but possible of course:
select a, substr(a,
instr(a, '-') + 1,
instr(a || '-', '-', 1, 2) - instr(a, '-') - 1
) as value
from mytable;
Demo: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=e75b878bbd6300e9207cd698bb3029ec

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

how to separate text from integer

I have addresses:
ALKOŅU 3-20;
M.LUBŠNAS 16V-9;
STIEBRU 6-22;
ANDREJA UPĪĀA IELA 16-2;
MISNKAS 4 -115;
CISKADI,BAZNICAS 4;
How it is possible in sql to separate first text part (district) from integer (house and flat number)?
Assuming the break-point is ALWAYS the first digit, then
SELECT RTRIM(LEFT(col, PATINDEX('%[0-9]%', col + '0') -1)) as District,
STUFF(col, 1, PATINDEX('%[0-9]%', col + '0') -1, '') as HouseAndFlat
FROM ...
e.g.
with t(col) as (
select
'ALKOŅU 3-20' union all select
'M.LUBŠNAS 16V-9' union all select
'STIEBRU 6-22' union all select
'ANDREJA UPĪĀA IELA 16-2' union all select
'MISNKAS 4 -115' union all select
'CISKADI,BAZNICAS 4')
SELECT RTRIM(LEFT(col, PATINDEX('%[0-9]%', col + '0') -1)) as District,
STUFF(col, 1, PATINDEX('%[0-9]%', col + '0') -1, '') as HouseAndFlat
FROM t