Oracle SQL: select last n qualifiers of a delimited string - sql

I have a delimited string in a column, and I want to select the last 5 qualifiers. For example, in the below example i would like to get the result '3,4,5,6,7'.
select '1,2,3,4,5,6,7' as val from dual
I am currently fiddling with reversing the string and trying to do a regexp_substr (maybe in combination with a regexp_count and a row_number?) on it, but I can't quite figure it out yet.
I can find several similar threads, but can't find the answer for oracle sql yet. If I find the solution I will post it here!

You can use regexp_substr():
select regexp_substr('1,2,3,4,5,6,7', '([^,]+[,]?){5}$')

You can try something like :
select substr(val, instr(val, ',', -1, 5) + 1)
This simply finds the fifth occurrence of ',' starting from the right and then returns the string from that character on

Related

Substring of a specific occurence

I have a column as varchar2 datatype, the data in it is in format:
100323.3819823.222
100.323123.443422
1001010100.233888
LOL12333.DDD33.44
I need to remove the whole part after the first occurrence of '.'
In the end it should look like this:
100323
100
1001010100
LOL12333
I cant seem to find the exact substring expression due to the fact that there is not any fix length of the first part.
One way is to use REGEXP_SUBSTR:
SELECT REGEXP_SUBSTR(column_name,'^[^.]*') FROM table
The other way is to combine SUBSTR with INSTR, which is a bit faster, but will result in NULL if the data doesn't contain a dot, so you'll have to add a switch if needed:
SELECT SUBSTR(column_name, 1, INSTR(column_name,'.') - 1) FROM table
For oracle you can try this:
select substr (i,1,Instr(i,'.',i)-1) from Table name.

Extracting specific part of column values in Oracle SQL

I want to extract a specific part of column values.
The target column and its values look like
TEMP_COL
---------------
DESCOL 10MG
TEGRAL 200MG 50S
COLOSPAS 135MG 30S
The resultant column should look like
RESULT_COL
---------------
10MG
200MG
135MG
This can be done using a regular expression:
SELECT regexp_substr(TEMP_COL, '[0-9]+MG')
FROM the_table;
Note that this is case sensitive and it always returns the first match.
I would probably approach this using REGEXP_SUBSTR() rather than base functions, because the structure of the prescription text varies from record to record.
SELECT TRIM(REGEXP_SUBSTR(TEMP_COL, '(\s)(\S*)', 1, 1))
FROM yourTable
The pattern (\s)(\S*) will match a single space followed by any number of non-space characters. This should match the second term in all cases. We use TRIM() to remove a leading space which is matched and returned.
how do you know what is the part you want to extract? how do you know where it begins and where it ends? using the white-spaces?
if so, you can use substr for cutting the data and instr for finding the white-spaces.
example:
select substr(tempcol, -- string
instr(tempcol, ' ', 1), -- location of first white-space
instr(tempcol, ' ', 1, 2) - instr(tempcol, ' ', 1)) -- length until next space
from dual
another solution is using regexp_substr (but it might be harder on performance if you have a lot of rows):
SELECT REGEXP_SUBSTR (tempcol, '(\S*)(\s*)', 1, 2)
FROM dual;
edit: fixed the regular expression to include expressions that don't have space after the parsed text. sorry about that.. ;)

SQL: Finding dynamic length characters in a data string

I am not sure how to do this, but I have a string of data. I need to isolate a number out of the string that can vary in length. The original string also varies in length. Let me give you an example. Here is a set of the original data string:
:000000000:370765:P:000001359:::3SA70000SUPPL:3SA70000SUPPL:
:000000000:715186816:P:000001996:::H1009671:H1009671:
For these two examples, I need 3SA70000SUPPL from the first and H1009671 from the second. How would I do this using SQL? I have heard that case statements might work, but I don't see how. Please help.
This works in Oracle 11g:
with tbl as (
select ':000000000:370765:P:000001359:::3SA70000SUPPL:3SA70000SUPPL:' str from dual
union
select ':000000000:715186816:P:000001996:::H1009671:H1009671:' str from dual
)
select REGEXP_SUBSTR(str, '([^:]*)(:|$)', 1, 8, NULL, 1) data
from tbl;
Which can be described as "look at the 8th occurrence of zero or more non-colon characters that are followed by a colon or the end of the line, and return the 1st subgroup (which is the data less the colon or end of the line).
From this post: REGEX to select nth value from a list, allowing for nulls
Sorry, just saw you are using DB2. I don't know if there is an equivalent regular expression function, but maybe it will still help.
For the fun of it: SQL Fiddle
first substring gets the string at ::: and second substring retrieves the string starting from ::: to :
declare #x varchar(1024)=':000000000:715186816:P:000001996:::H1009671:H1009671:'
declare #temp varchar(1024)= SUBSTRING(#x,patindex('%:::%', #x)+3, len(#x))
SELECT SUBSTRING( #temp, 0,CHARINDEX(':', #temp, 0))

Select PART of a SQL field between two known string elements

I am looking to extract only a portion of a string from a comment field in a SQL table. The current string looks like this: "TN:mba trucking|HR:cf82267|TR:solomon|AI:|N/A". What I want to do is to select anything from TN: up until the next pipe. Then I want to select anything from HR: up until the next pipe. Note, the data between these parameters are not always the same length, therefore cannot use SUBSTRING.
For Oracle you could use instr and substr, to be flexible according to different stringlength. In my example I did not create a table where I could select your samplestring from. Therefore it's a bit clunky. If you can use normal fieldnames instead of repeating the string it will look much more compact.
SELECT SUBSTR('TN:mba trucking|HR:cf82267|TR:solomon|AI:|N/A',
INSTR('TN:mba trucking|HR:cf82267|TR:solomon|AI:|N/A', 'TN:'),
INSTR('TN:mba trucking|HR:cf82267|TR:solomon|AI:|N/A', '|') - 1)
FROM dual;
I included the -1 to cut the pipe off. If you want to, you can cut the TN: off too. This is a very basic way and not the best solution. You will get problems, if the text contains some of the keywords you are looking for in the instr-function. Depending on the overall context it may be wise to use some regex, like simsim mentioned before.
For example:
I wrote this code to get me the list of numbers inside a string
SELECT DISTINCT A.REZ FROM
(
SELECT REGEXP_SUBSTR('1213-1201+1202+1203+1204+1205+1206+1207+1208+1209+1210+1211', '[0-9]+', 1, LEVEL) AS REZ FROM dual
CONNECT BY REGEXP_SUBSTR('1213-1201+1202+1203+1204+1205+1206+1207+1208+1209+1210+1211', '[0-9]+', 1, LEVEL) IS NOT NULL
) A;
you can write your regular expression to get the words from between each pipe
so, it will be something like this:
SELECT A.REZ FROM
(
SELECT REGEXP_SUBSTR(Your_Var, Your_Regular_Expression, 1, LEVEL) AS REZ FROM dual
CONNECT BY REGEXP_SUBSTR(Your_Var, Your_Regular_Expression, 1, LEVEL) IS NOT NULL
) A;
Where Your_Var will hold the text you want to work with
And Your_Regular_Expression will be the Regular Expression that you need to construct to meet your needs
Note: this is Oracle Sql Syntax

How to get rightmost 10 places of a string in oracle

I am trying to fetch an id from an oracle table. It's something like TN0001234567890345. What I want is to sort the values according to the right most 10 positions (e.g. 4567890345). I am using Oracle 11g. Is there any function to cut the rightmost 10 places in Oracle SQL?
You can use SUBSTR function as:
select substr('TN0001234567890345',-10) from dual;
Output:
4567890345
codaddict's solution works if your string is known to be at least as long as the length it is to be trimmed to. However, if you could have shorter strings (e.g. trimming to last 10 characters and one of the strings to trim is 'abc') this returns null which is likely not what you want.
Thus, here's the slightly modified version that will take rightmost 10 characters regardless of length as long as they are present:
select substr(colName, -least(length(colName), 10)) from tableName;
Another way of doing it though more tedious. Use the REVERSE and SUBSTR functions as indicated below:
SELECT REVERSE(SUBSTR(REVERSE('TN0001234567890345'), 1, 10)) FROM DUAL;
The first REVERSE function will return the string 5430987654321000NT.
The SUBSTR function will read our new string 5430987654321000NT from the first character to the tenth character which will return 5430987654.
The last REVERSE function will return our original string minus the first 8 characters i.e. 4567890345
SQL> SELECT SUBSTR('00000000123456789', -10) FROM DUAL;
Result: 0123456789
Yeah this is an old post, but it popped up in the list due to someone editing it for some reason and I was appalled that a regular expression solution was not included! So here's a solution using regex_substr in the order by clause just for an exercise in futility. The regex looks at the last 10 characters in the string:
with tbl(str) as (
select 'TN0001239567890345' from dual union
select 'TN0001234567890345' from dual
)
select str
from tbl
order by to_number(regexp_substr(str, '.{10}$'));
An assumption is made that the ID part of the string is at least 10 digits.