Oracle - split the string by comma and get the last sub-str - regex

I wanted to write an Oracle query to extract only the last sub-string of comma separated string like below:
DEST = "1,MMA SALAI,ARIANKUPAM,CITY CENTRE,G12 47H"
I am interested in only G12. How do I get in the Oracle query?
Thanks

Try
REGEXP_SUBSTR('1,MMA SALAI,ARIANKUPAM,CITY CENTRE,G12 47H', '[^,]+$')
But that will fetch G12 47H. You may consider
REGEXP_SUBSTR('1,MMA SALAI,ARIANKUPAM,CITY CENTRE,G12 47H', '([^, ]+)( +[^,]*)?$', 1,1,NULL,1)
This will give G12.

A little bit of substringing (see comments within the code):
SQL> with test (dest) as
2 (select '1,MMA SALAI,ARIANKUPAM,CITY CENTRE,G12 47H' from dual)
3 select
4 regexp_substr(dest, --> out of the DEST, give me ...
5 '\w+', --> ... the first word that begins right after ...
6 instr(dest, ',', 1, regexp_count(dest, ',')) + 1 --> ... postition of the last
7 ) result --> comma in the source string
8 from test;
RESULT
--------------------
G12
SQL>
Or, by splitting the comma-separated values into rows:
SQL> with test (dest) as
2 (select '1,MMA SALAI,ARIANKUPAM,CITY CENTRE,G12 47H' from dual)
3 select regexp_substr(col, '\w+') result
4 from (select regexp_substr(dest, '[^,]+', 1, level) col, --> split column to rows
5 row_number() over (order by level desc) rn --> the last row will be RN = 1
6 from test
7 connect by level <= regexp_count(dest, ',') + 1
8 )
9 where rn = 1;
RESULT
--------------------
G12
SQL>

Related

How to extract digit from string in SQL?

I have a string which has at least one digit per bracket. Now, I want to extract the digit(s). How do I do this in Redshift sql?
ColumnA ColumnB (output)
(,,,3,) 3
(2,,,) 2
(,,,1) 1
(1,,,3) 13
You could use REGEXP_REPLACE. Here's a snippet:
CREATE TABLE x (col1 varchar(255))
INSERT INTO x VALUES ('(,,,3,)'),('(2,,,)'),('(,,,1)'),('(1,,,3)');
select col1,
regexp_replace(col1,'[^\d]','','g') as col2
from x;
col1
col2
(,,,3,)
3
(2,,,)
2
(,,,1)
1
(1,,,3)
13
Try it in SQLFiddle
Jakob's answer would work. You can also do the same thing with REPLACE:
CREATE TABLE x (col1 varchar(255))
INSERT INTO x VALUES ('(,,,3,)'),('(2,,,)'),('(,,,1)'),('(1,,,3)')
SELECT REPLACE(
REPLACE(
REPLACE(
col1, ',', ''
) ,')', ''
), '(', ''
) FROM x
replace
3
2
1
13
SQLFiddle

search substring in string

I'm looking for a regexp to get the correct output
For my example:
SELECT regexp_substr('brablcdefghig', '[^(bl)]+$') FROM dual;
I expect evth what is follow 'bl': cdefghig and it's OK,
But when I modify input and add 'b' charcter I've NULL in output why?
SELECT regexp_substr('brablcdefghigb', '[^(bl)]+$') FROM dual;
That's a simple substr + instr; you don't need regular expressions. If it has to be regexp, see lines #8 and 9
SQL> with test (id, col) as
2 (select 1, 'brablcdefghig' from dual union all
3 select 2, 'brablcdefghigb' from dual
4 )
5 select id,
6 col,
7 substr(col, instr(col, 'bl') + 2) result,
8 regexp_substr(replace(col, 'bl', '#'), '[^#]+$') result2,
9 regexp_replace(col, '.+bl', '') result3
10 from test;
ID COL RESULT RESULT2 RESULT3
---------- -------------- ---------- ---------- ----------
1 brablcdefghig cdefghig cdefghig cdefghig
2 brablcdefghigb cdefghigb cdefghigb cdefghigb
SQL>

I want to know how to execute CONNECT BY REGEXP in Google Big query

I have following statement in oracle sql I want to run this in Google Big Query.
CONNECT BY REGEXP_SUBSTR(VALUE, '[^,]+', 1, LEVEL) IS NOT NULL)
How can I run above code in Big query?
I am guessing here - but usually this construct is used for so called string decomposition
So, in BigQuery you can use SPLIT(value) or REGEXP_EXTRACT_ALL(value, r'[^,]+') for this as in below examples
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, '1,2,3,4,5,6,7' AS value UNION ALL
SELECT 2, 'a,b,c,d'
)
SELECT id, SPLIT(value) value
FROM `project.dataset.table`
or
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, '1,2,3,4,5,6,7' AS value UNION ALL
SELECT 2, 'a,b,c,d'
)
SELECT id, REGEXP_EXTRACT_ALL(value, r'[^,]+') value
FROM `project.dataset.table`
both above query will return
Row id value
1 1 1
2
3
4
5
6
7
2 2 a
b
c
d
Here, as you can see - value in each row gets split into array of elements but still in the same row
To flatten result you can further use UNNEST() as in below examples
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, '1,2,3,4,5,6,7' AS value UNION ALL
SELECT 2, 'a,b,c,d'
)
SELECT id, value
FROM `project.dataset.table`,
UNNEST(SPLIT(value)) value
or
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, '1,2,3,4,5,6,7' AS value UNION ALL
SELECT 2, 'a,b,c,d'
)
SELECT id, value
FROM `project.dataset.table`,
UNNEST(REGEXP_EXTRACT_ALL(value, r'[^,]+')) value
both return below result (with all extracted elements in separate row)
Row id value
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
6 1 6
7 1 7
8 2 a
9 2 b
10 2 c
11 2 d

oracle regexp_like , specific number format without negative lookahead

I'm using regexp_like function in Oracle in order to match the following number format : xxxyxxx
I'm trying this :
select 1 "val"
from dual
where regexp_like('5553555','^(\d){3}(?!\1)\d\1{3}$')
but as I realized, negative lookahead is not supported in Oracle.
how to do it without negative lookahead?
Indeed, no look around is possible. Please note that you also have another issue: (\d){3} will match also 3 different digits. You would need (\d)\1\1 to match only three of the same digits.
For your particular case you could still use a regular expression. What I could think of is using a particular property: numbers with all the same 7 digits (xxxxxxx) will be dividable by 1111111.
With regexp_like and an additional modulo test:
with tbl(val) as (
select '5555555' from dual union
select '5553555' from dual union
select 'nothing' from dual
)
select val
from tbl
where regexp_like(val,'^(\d)\1\1\d\1{3}$') and mod(val, 1111111) > 0;
Or you could use two regexes:
with tbl(val) as (
select '5555555' from dual union
select '5553555' from dual union
select 'nothing' from dual
)
select val
from tbl
where regexp_like(val,'^(\d)\1\1\d\1{3}$') and not regexp_like(val,'^(\d)..\1');
Admittedly, neither is really elegant, and also not the most efficient. For more efficiency you should not use regular expressions.
Maybe oldfashioned SUBSTR might help. Something like this: split input string (COL) into two equal pieces, and compare whether they match. LEN is used to distinguish odd from even lengths and what to do with the second part of the string (i.e. which is its starting point).
A few examples:
SQL> WITH test (col) AS (SELECT '5554555' FROM DUAL),
2 len AS (SELECT LENGTH (col) len FROM test)
3 SELECT CASE
4 WHEN SUBSTR (col, 1, TRUNC (LENGTH (col) / 2)) =
5 SUBSTR (
6 col,
7 TRUNC (LENGTH (col) / 2)
8 + CASE WHEN MOD (l.len, 2) = 0 THEN 1 ELSE 2 END)
9 THEN
10 'OK'
11 ELSE
12 'Not OK'
13 END
14 result
15 FROM test t, len l;
RESULT
------
OK
SQL> l1
1* WITH test (col) AS (SELECT '5554555' FROM DUAL),
SQL> c/5554/2234/
1* WITH test (col) AS (SELECT '2234555' FROM DUAL),
SQL> /
RESULT
------
Not OK
SQL> l1
1* WITH test (col) AS (SELECT '2234555' FROM DUAL),
SQL> c/2234555/1221/
1* WITH test (col) AS (SELECT '1221' FROM DUAL),
SQL> /
RESULT
------
Not OK
SQL> l1
1* WITH test (col) AS (SELECT '1221' FROM DUAL),
SQL> c/1221/8888/
1* WITH test (col) AS (SELECT '8888' FROM DUAL),
SQL> /
RESULT
------
OK
SQL>
Use of the Trim Function to Trim Off The 'X' Values from 'Y'
This is just another approach to solving this subset of numeric palindrome problems.
If this were just a numeric palindrome, the undocumented function, reverse, could be used. Since we have a Y for the midvalue and we are testing to make sure that Y is not equal to X, the reverse function does not help us a lot here.
Borrowing on the use of subexpressions (aka character grouping) approach that Trincot uses, I just create a second subexpression for the midvalue and then I trim off the midvalue. If the trimmed expression is equal to original value, then we can be assured that Y != X.
SCOTT#db>WITH tst ( val ) AS (
2 SELECT '5555555' FROM DUAL UNION ALL
3 SELECT '12121' FROM DUAL UNION ALL
4 SELECT '5553555' FROM DUAL UNION ALL
5 SELECT 'amanaplanpanama' FROM DUAL UNION ALL
6 SELECT '' FROM DUAL
7 ) SELECT
8 val,
9 REGEXP_SUBSTR(val,'^(\d)\1\1(\d)\1{3}$',1,1,NULL,2) midval,
10 TRIM(BOTH REGEXP_SUBSTR(val,'^(\d)\1\1(\d)\1{3}$',1,1,NULL,2) FROM val) trim_midval
11 FROM
12 tst
13 WHERE
14 1 = 1
15 AND val = TRIM(BOTH regexp_substr(val,'^(\d)\1\1(\d)\1{3}$',1,1,NULL,2) FROM val);
-----------------------------
VAL MIDVAL TRIM_MIDVAL
5553555 3 5553555
-----------------------------
Littlefoot's non-regular expression solution appears to be the most straightforward here.

Extract string from a large string oracle regexp

I have String as below.
select b.col1,a.col2,lower(a.col3) from table1 a inner join table2 b on a.col = b.col and a.col = b.col
inner join (select col1, col2, col3,col4 from tablename ) c on a.col1=b.col2
where
a.col = 'value'
Output need to be table1,table2 and tablename from above string. please let me know the regex to get the result.
Should be a simple one :-)
SQL> WITH DATA AS(
2 select q'[select b.col1,a.col2,lower(a.col3) from table1 a inner join table2 b on
3 a.col = b.col and a.col = b.col inner join (select col1, col2, col3,col4 from tablename )
4 c on a.col1=b.col2 where a.col = 'value']' str
5 FROM DUAL)
6 SELECT LISTAGG(TABLE_NAMES, ' , ') WITHIN GROUP (
7 ORDER BY val) table_names
8 FROM
9 (SELECT 1 val,
10 regexp_substr(str,'table[[:alnum:]]+',1,level) table_names
11 FROM DATA
12 CONNECT BY level <= regexp_count(str,'table')
13 )
14 /
TABLE_NAMES
--------------------------------------------------------------------------------
table1 , table2 , tablename
SQL>
Brief explanation, so that OP/even others might find it useful :
The REGEXP_SUBSTR looks for the words 'table', it could be followed
by a number or string like 1,2, name etc.
To find all such words, I used connect by level technique, but it
gives the output in different rows.
Finally, to put them in a single row as comma separated values, I
used LISTAGG.
Oh yes, and that q'[]' is the string literal technique.