Select specific data after defined decimal - sql

I have a column that contains version information in a format like:
20.6.4.4200
10.28.30.2678
22.8.34.1200
I’m wanting to only select the values after the last decimal like:
4200
2678
1200
What is the best way to do this or is a Regex needed?

In SQL Server, that has poor regex support, you can use string functions as follows:
right(val, charindex('.', reverse(val)) - 1)
The idea is to get the position of the last dot in the string, counting from the end of the string, then extract the relevant part of the string with right().
Demo on DB Fiddle:
select val, right(val, charindex('.', reverse(val)) - 1) new_val
from (values('20.6.4.4200'), ('10.28.30.2678'), ('22.8.34.1200')) t(val)
GO
val | new_val
:------------ | :------
20.6.4.4200 | 4200
10.28.30.2678 | 2678
22.8.34.1200 | 1200

A regular expression is probably the simplest method. Databases that support regular expressions usually support something that retrieves a substring. The syntax would be like:
select regexp_substr(col, '[0-9]+$')
Of course, the function might have a different name.

Related

SQL - trimming values before bracket

I have a column of values where some values contain brackets with text which I would like to remove. This is an example of what I have and what I want:
CREATE TABLE test
(column_i_have varchar(50),
column_i_want varchar(50))
INSERT INTO test (column_i_have, column_i_want)
VALUES ('hospital (PWD)', 'hopistal'),
('nursing (LLC)','nursing'),
('longterm (AT)', 'longterm'),
('inpatient', 'inpatient')
I have only come across approaches that use the number of characters or the position to trim the string, but these values have varying lengths. One way I was thinking was something like:
TRIM('(*',col1)
Doesn't work. Is there a way to do this in postgres SQL without using the position? THANK YOU!
If all the values contain "valid" brackets, then you may use split_part function without any regular expressions:
select
test.*,
trim(split_part(column_i_have, '(', 1)) as res
from test
column_i_have | column_i_want | res
:------------- | :------------ | :--------
hospital (PWD) | hopistal | hospital
nursing (LLC) | nursing | nursing
longterm (AT) | longterm | longterm
inpatient | inpatient | inpatient
db<>fiddle here
You can replace partial patterns using regular expressions. For example:
select *, regexp_replace(v, '\([^\)]*\)', '', 'g') as r
from (
select '''hospital (PWD)'', ''nursing (LLC)'', ''longterm (AT)'', ''inpatient''' as v
) x
Result:
r
-------------------------------------------------
'hospital ', 'nursing ', 'longterm ', 'inpatient'
See example at db<>fiddle.
Could it be as easy as:
SELECT SUBSTRING(column_i_have, '\w+') AS column_i_want FROM test
See demo
If not, and you still want to use SUBSTRING() to get upto but exclude paranthesis, then maybe:
SELECT SUBSTRING(column_i_have, '^(.+?)(?:\s*\(.*)?$') AS column_i_want FROM test
See demo
But if you really are looking upto the opening paranthesis, then maybe just use SPLIT_PART():
SELECT SPLIT_PART(column_i_have, ' (', 1) AS column_i_want FROM test
See demo

Retrieve text between two periods in a value

I’ve been spinning around a bit on how to accomplish this in SQL DW. I need to extract the text between two periods in a returned value. So my value returned for Result is:
I’m trying to extract the values between period 1 and 2, so the red portion above:
The values will be a wide variety of lengths.
I’ve got this code:
substring(Result,charindex('.',Result)+1,3) as ResultMid
that results in this:
My problem is I’m not sure how to get to a variable length to return so that I can pull the full value between the two periods. Would someone happen to know how I can accomplish this?
Thx,
Joe
We can build on your current attempt:
substring(
result,
charindex('.', result) + 1,
charindex('.', result, charindex('.', result) + 1) - charindex('.', result) - 1
)
Rationale: you alreay have the first two arguments to substring() right. The third argument defines the number of characters to capture. For this, we compute the position of the next dot (.) with expression: charindex('.', result, charindex('.', result) + 1). Then we substract the position of the first dot from that value, which gives us the number of characters that we should capture.
Demo on DB Fiddle:
result | result_mid
:----------------------- | :---------
sam.pdc.sys.paas.l.com | pdc
sm.ridl.sys.paas.m.com | ridl
s.sandbox.sys.paas.g.com | sandbox
If you are dealing with up to 128 characters per delimited part of the string, try parsename as below. Otherwise, GMB has a pretty solid solution up there.
select *, parsename(left(result,charindex('.',result,charindex('.',result)+1)-1),1) as mid
from your_table;
Another method that you can easily modify to extract 3rd, 4th...(hopefully not too remote) part of the string using cross apply.
select result, mid
from your_table t1
cross apply (select charindex('.',result) as i1) t2
cross apply (select charindex('.',result,(i1 + 1)) as i2) t3
cross apply (select substring(result,(i1+1),(i2-i1-1)) as mid) t4;
DEMO

PostgreSQL - Extract string before ending delimiter

I have a column of data that looks like this:
58,0:102,56.00
52,0:58,68
58,110
57,440.00
52,0:58,0:106,6105.95
I need to extract the character before the last delimiter (',').
Using the data above, I want to get:
102
58
58
57
106
Might be done with a regular expression in substring(). If you want:
the longest string of only digits before the last comma:
substring(data, '(\d+)\,[^,]*$')
Or you may want:
the string before the last comma (',') that's delimited at the start either by a colon (':') or the start of the string.
Could be another regexp:
substring(data, '([^:]*)\,[^,]*$')
Or this:
reverse(split_part(split_part(reverse(data), ',', 2), ':', 1))
More verbose but typically much faster than a (expensive) regular expression.
db<>fiddle here
Can't promise this is the best way to do it, but it is a way to do it:
with splits as (
select string_to_array(bar, ',') as bar_array
from foo
),
second_to_last as (
select
bar_array[cardinality(bar_array)-1] as field
from splits
)
select
field,
case
when field like '%:%' then split_part (field, ':', 2)
else field
end as last_item
from second_to_last
I went a little overkill on the CTEs, but that was to expose the logic a little better.
With a CTE that removes everything after the last comma and then splits the rest into an array:
with cte as (
select
regexp_split_to_array(
replace(left(col, length(col) - position(',' in reverse(col))), ':', ','),
','
) arr
from tablename
)
select arr[array_upper(arr, 1)] from cte
See the demo.
Results:
| result |
| ------ |
| 102 |
| 58 |
| 58 |
| 57 |
| 106 |
The following treats the source string as an "array of arrays". It seems each data element can be defined as S(x,y) and the overall string as S1:S2:...Sn.
The task then becomes to extract x from Sn.
with as_array as
( select string_to_array(S[n], ',') Sn
from (select string_to_array(col,':') S
, length(regexp_replace(col, '[^:]','','g'))+1 n
from tablename
) t
)
select Sn[array_length(Sn,1)-1] from as_array
The above extends S(x,y) to S(a,b,...,x,y) the task remains to extracting x from Sn. If it is the case that all original sub-strings S are formatted S(x,y) then the last select reduces to select Sn[1]

How to trim data with last alphanumeric key as reference

Need your help on below Data trimming or what so ever to get the result that shows also on below. I want to get the data where my reference is the last - symbol.
See example below.
FROM TO
+-------------------------------+
|ABC-1234-AR-R | ABC-1234-AR |
|ABC-1254-AR-IT | ABC-1254-AR |
|ABC-1223-AR-LTL| ABC-1223-AR |
|ABC-1234-R | ABC-1234 |
+-------------------------------+
This will give you index of last occurence of a hyphen:
LEN(data) - CHARINDEX('-', REVERSE(data)) + 1
So it's enough to take substring of this length:
SELECT
data,
SUBSTRING(data, 1, LEN(data) - CHARINDEX('-', REVERSE(data))) AS data_trimmed
FROM yourTable;
Demo
You can also use a combination of LEFT and CHARINDEX functions.
Query
select [from],
left([from], len([from]) - charindex('-', reverse([from]), 1)) as [to]
from [your_table_name];
Find a demo here

Regular Expression - Retrieve specific asterisk separated value string

I need to retrieve a specific part of a string which has values separated by asterisk's
In the example below I need to retrieve the string Client Contact Centre Seniors2 which sits between the 6 and 7 asterisk.
I am fairly new to regular expressions and have only managed to find select a value between 2 asterisks using *[\w]+*
Is there a way to specify which number of asterisk to look at using regular expression, or is there a better way for me to retrieve the string I am after?
String:
2*J25*Owner11*Owner Group2*L231*CLIENTCONTACTCENTRESENIORSQUEUE29*Client Contact Centre Seniors2*K20*0*2*C110*SR_STAT_ID2*N18*Referred2*O10*
Note: I will be using this regular expression in Oracle SQL using REGEXP_LIKE(string, regex).
* is a regex operator and needs to be escaped, unless used inside brackets that holds character list. You can use this simplified pattern to extract the
seventh word.
regexp_substr(Audits.audit_log,'[^*]+',1,7)
SQL Fiddle
Query 1:
with x(y) as (
select '2*J25*Owner11*Owner Group2*L231*CLIENTCONTACTCENTRESENIORSQUEUE29*Client Contact Centre Seniors2*K20*0*2*C110*SR_STAT_ID2*N18*Referred2*O10*'
from dual
)
select regexp_substr(y,'([^*]+)\*',1,7,null,1)
from x
Results:
| REGEXP_SUBSTR(Y,'([^*]+)\*',1,7,NULL,1) |
|-----------------------------------------|
| Client Contact Centre Seniors2 |
Query 2:
with x(y) as (
select '2*J25*Owner11*Owner Group2*L231*CLIENTCONTACTCENTRESENIORSQUEUE29*Client Contact Centre Seniors2*K20*0*2*C110*SR_STAT_ID2*N18*Referred2*O10*'
from dual
)
select regexp_substr(y,'[^*]+',1,7)
from x
Results:
| REGEXP_SUBSTR(Y,'[^*]+',1,7) |
|--------------------------------|
| Client Contact Centre Seniors2 |
You could also use INSTR and SUBSTR for that. Simple and fast, but not as concise as the REGEXP_SUBSTR.
with t as (
select '2*J25*Owner11*Owner Group2*L231*CLIENTCONTACTCENTRESENIORSQUEUE29*Client Contact Centre Seniors2*K20*0*2*C110*SR_STAT_ID2*N18*Referred2*O10*' testvalue
from dual
)
select substr(testvalue, instr(testvalue, '*', 1, 6)+1, instr(testvalue, '*', 1, 7) - instr(testvalue, '*', 1, 6) - 1)
from t;