substring with variable last character SQL Server - sql

I have a number of rows in a database column that look like this
AB01-52
AB01-52/1
AB01-53/2
AB01-54
I can get the 52 where there is no slash in the string but when I try to get it between the dash and the slash I either get an error or get the 52/1 for example
I have tried most of the researched solutions using substring and charindex but to no avail
Has anyone seen a solution for this.
Thanks in advance
Rick

You can subtract the characters positions (i.e. /) and use as length for substring()
substring(col, charindex('-', col)+1, len(col)-charindex('/', col)+1)
If the numbers have variable length then do the subtraction from both characters and use of length
substring(col, charindex('-', col)+1, charindex('/', col+'/')-charindex('-', col)-1)

Here's one approach....
with cte as(
select 'AB01-53/2' as C1
union
select 'AB01-54')
select left(right(c1,len(c1) - charindex('-',c1)),len(right(c1,len(c1) - charindex('-',c1))) - charindex('/',right(c1,len(c1) - charindex('-',c1)))+ 1)
from cte

If the field is ALWAYS AAAA-BB[/CCC], then simply:
SUNSTRING('AB01-52/1',6,2) ;
Of course, the 'AB01-52/1' may be substituted by a variable or column name.

I may have found an answer but it involves a 2 stage process
First add an additional slash to the column that contains the data where there is no slash at the moment ie AB01-52 becomes AB01-52/ the others like AB01-1023/01 remain the same
stage 2 use this code:
substring(right(col1,len(col1)-charindex('-',col1)),0,charindex('/',right(col1,len(col1)-charindex('-',col1))))
this allows me to get the middle string. The use of left and right by various people who contributed helped to get to this - however I still thing there should be an answer without stage 1
Thanks you all for your ideas which got me to this point

Related

SnowflakeSQL get me last text after specific char

I'm trying to retrieve last part of string after underscore.. but every record has different number of underscore and I'm not sure how to write it correctly.
Example:
aaa_bb_cccc_dddd_ee - only ee
aaa_bb_cccc_dddd - only dddd
sss_aas_ww_ww_ww_bb - only bb
As you can see there is different number of underscore and I need only last part after last underscore.
I have been playing with regex and split_part but since I don't now how to point to the last _ then it's not working correctly.
My Idea is to start reading string from the right a then you just pick the first one but couldn't find a way how to do it.
It's probably basic thing but I'm struggling with it so please help.
Use REGEXP_SUBSTR:
SELECT col, REGEXP_SUBSTR(col, '_([^_]+)$', 1, 1, 'e', 1) AS col_out
FROM yourTable;
You can make split_part change the direction of split using negative integers
select split_part(col,'_',-1)
from your_table;
You could also just regexp_replace everything up until and including the last underscore
select regexp_replace(col,'.*_','')
from your_table;

Trim a character on SQL

Hi everyone this is my first time that i asked something.
I have multiple codes on my db with numbers and '/', for example:
510325205
510325205/000/01
510565025-01
510565025-01/090/03
...
I need to trim the / - I need these results:
510325205
510325205
510565025-01
510565025-01
...
I already searched and tried this
left(code, charindex('/', code))
and it works for the codes with / in it, but the codes without / are excluded from the results.
Thanks for your help!
Your try was very close.
All you needed to add was -1.
As you can see the explanation for the left() function:
The LEFT() function extracts a number of characters from a string
(starting from left): LEFT(string, number_of_chars)
With charindex() function you have told the left() function how many characters to take. By adding -1 to that you have removed the '/' sign because you have told the LEFT() function to take 10 characters and not 11(for example) because 11th character is '/'.
select left('510325205/000/01',charindex('/','510325205/000/01')-1)
or because you have column named code
select left(code,charindex('/',code)-1)
If you have values without / you can use this:
select case when charindex('/',code_c)-1 = -1
then
code_c
else
left(code_c,charindex('/',code_c)-1)
end RESULT
from test
OR
select left(code_c,iif(charindex('/',code_c)-1 = -1, len(code_c), charindex('/',code_c)-1))
from test
Here is DEMO

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.. ;)

Comparing fields when a field has data in between 2 characters that match the field being compared

I have code that looks like this:
left outer join
gme_batch_header bh
on
substr(ln.lot_number,instr(ln.lot_number,'(') + 1,
instr(ln.lot_number,')') - instr(ln.lot_number,'(') - 1)
=
bh.batch_no
It works fine, but I have come across a few lot numbers that have two sections of strings that are between parenthesis. How would I compare what is between the second set of parenthesis? Here is an example of the data in the lot number field:
E142059-307-SCRAP-(74055)
This one works with the code,
58LF-3-B-2-2-2 (SCRAP)-(61448)
This one tries comparing SCRAP with the batch no, which isn't correct. It needs to be the 61448.
The result is always the last item in parenthesis.
After more research, I actually got it to work with this code:
substr(ln.lot_number,instr(ln.lot_number,'(',-1) + 1, instr(ln.lot_number,')',-1) - instr(ln.lot_number,'(',-1) - 1)
Assuming SQL2005+, and it is always the last occurrence you want, then I would suggest finding the last instance of a ( in your query and substring to there. To get the last instance you could use something like:
REVERSE(SUBSTRING(REVERSE(lot_number),0,CHARINDEX('(',REVERSE(lot_number))))
If your version of Oracle supports regular expressions try this:
substr(regexp_substr(ln.lot_number,'[0-9]+\)$'),1,length(regexp_substr(ln.lot_number,'[0-9]+\)$'))-1)
Explanation:
regexp_substr(scrap_row,'[0-9]+\)$' ==> find me just numbers in the string that ends in ). This returns the numbers but it includes the closing parenthesis.
To remove the closing parenthsis, just send it through substring and extract first number through the length of the number stopping at 1 character from the end of the string.
Query for analysis:
with scrap
as (select '58LF-3-B-2-2-2 (SCRAP)-(61448)' as scrap_row from dual)
select scrap_row,
regexp_substr(scrap_row,'[0-9]+\)$') as regex_substring,
length(regexp_substr(scrap_row,'[0-9]+\)$')) as length_regex_substring,
substr(regexp_substr(scrap_row,'[0-9]+\)$'),1,length(regexp_substr(scrap_row,'[0-9]+\)$'))-1) as regex_sans_parenthesis
from scrap
If you have 11g, this will do it pretty simply by using the subgroup argument of regexp_substr() and constructing the regex appropriately:
SQL> with tbl(data) as
(
select 'E142059-307-SCRAP-(74055)' from dual
union
select '58LF-3-B-2-2-2 (SCRAP)-(61448)' from dual
)
select data from tbl
where regexp_substr(data, '\((\d+)\)$', 1, 1, NULL, 1)
= '61448';
DATA
------------------------------
58LF-3-B-2-2-2 (SCRAP)-(61448)
The regular expression can be read as:
\( - Search for a literal left paren
( - Start a remembered subgroup
\d+ - followed by 1 more more digits
) - End remembered subgroup
\) - followed by a literal right paren
$ - at the end of the line.
The regexp_substr function arguments are:
Source - the source string
Pattern - The regex pattern to look for
position - Position in the string to start looking for the pattern
occurrence - If the pattern occurs multiple times, which occurrence you want
match_params - See the docs, not used here
subexpression - which subexpression to use (the remembered group)
So in English, look for a series of 1 or more digits surrounded by parens, where it occurs at the end of the line and save the digit part only to use to compare. IMHO a lot easier to follow/maintain than nested instr(), substr().
For re-useability, make a function called get_last_number_in_parens() that contains this code and uses an argument of the string to search. This way that logic is encapsulated and can be re-used by folks that may not be so comfortable with regular expressions, but can benefit from the power! One place to maintain code too. Then call like this:
select data from tbl
where get_last_number_in_parens(data) = '61448';
How easy is that?!
Hello you can check with this code. It works whaever the condition may be
SELECT SUBSTR('58LF-3-B-2-2-2-(61448)',instr('58LF-3-B-2-2-2-(61448)','(',-1)+1,LENGTH('58LF-3-B-2-2-2-(61448)')-instr('58LF-3-B-2-2-2-(61448)','(',-1)-1)
FROM dual;
SELECT SUBSTR('58LF-3-B-2-2-2 (SCRAP)-(61448)',instr('58LF-3-B-2-2-2 (SCRAP)-(61448)','(',-1)+1,LENGTH('58LF-3-B-2-2-2 (SCRAP)-(61448)')-instr('58LF-3-B-2-2-2 (SCRAP)-(61448)','(',-1)-1)
FROM dual;
Output
==================================
61448
==================================

How can I use RTRIM or REPLACE when I know the length I want to trim but not what it may contain?

I need to RTRIM the last 7 characters from a result set in an Oracle query. These 7 chars can be anything; spaces, alpha numeric etc... and I don't know the exact length of any value.
So for example I'd like to run something like this
SELECT RTRIM (COl_A, (SELECT LENGTH (COL_A)-7) FROM TABLE_ONE;
or a replace equivalent
SELECT REPLACE(COL_A, (SELECT LENGTH (COL_A)-7 FROM TABLE_ONE),'');
Do I need to do something with SUBSTRING maybe?
I know how to remove/replace specific chars but I'm having trouble when dealing with unknown chars. I've seen a few examples of similar problems but they seem unnecessarily complicated... or does this require a more in depth solution than I think it should?
As always thanks in advance for advice or hints.
You are in search of the substr function.
select substr(col_a, 1, length(col_a) - 7) from table_one
Actually, the correct solution is:
select substr(col_a, 1, (case when length(col_a) < 7 then 0 else length(col_a) - 7 end) from table_one
To be general, you would want to take into account what happens when the length is less than 7.