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
Related
I have a nvarchar string from which I need to extract certain text from between characters.
Example: 1.abc.5,m001-1-Exit,822-FName-18001233321--2021-09-23 13:53:10 Thursday-m001-1-Exit-Swipe,Card NO: 822User ID: FNameName: 18001233321Dept: Read Date: 2021-09-23 13:53:10 ThursdayAddr: m001-1-ExitStatus: Swipe,07580ec2000002a52E917D0000000000372BA56E11010000
What I need:
| Name | Phone Number |
| -------- | -------------- |
| FName | 1800123321 |
My Attempt:
SELECT SUBSTRING(col, LEN(LEFT(col, CHARINDEX ('-', col))) + 1, LEN(col) - LEN(LEFT(col, CHARINDEX ('-', col))) - LEN(RIGHT(col, LEN(col) - CHARINDEX ('-', col))) - 1);
One way:
Use patindex to find "FName-"
Remove the start of the string up until and including "FName-"
Use patindex to find "--"
Remove the rest of the string from and including "--"
You can consolidate the query down to one line, but you'll find yourself repeating parts of the logic - which I like to avoid. And calculating one thing at a time makes it easier to debug.
select
A.Col
, B.StringStart
, C.NewString
, patindex('%--%',C.NewString) NewStringEnd
, substring(C.NewString,1,patindex('%--%',C.NewString)-1) -- <- Required Result
from (
values
(N'1.abc.5,m001-1-Exit,822-FName-18001233321--2021-09-23 13:53:10 Thursday-m001-1-Exit-Swipe,Card NO: 822User ID: FNameName: 18001233321Dept: Read Date: 2021-09-23 13:53:10 ThursdayAddr: m001-1-ExitStatus: Swipe,07580ec2000002a52E917D0000000000372BA56E11010000')
) A (Col)
cross apply (
values
(patindex('%FName-%',Col))
) B (StringStart)
cross apply (
values
(substring(A.Col,B.StringStart+6,len(A.Col)-B.StringStart-6))
) C (NewString);
I'm trying to use LTRIM to split the following field 'hours' - trimming off the characters from the left up to and including the pipe | symbol.
Monday|11:00-18:00
to result in
11:00-18:00
I would have thought the following code is correct
LTRIM(hours, '%|')
But it just isn't working. The query runs but the above statement has no affect. Can anyone help?
Many thanks
Richard
Use instr() to compute the position of the pipe character in the string, and substr() to select everything after that position:
substr(col, instr(col, '|') + 1) as newcol
Demo on DB Fiddle:
with t as (select 'Monday|11:00-18:00' col)
select substr(col, instr(col, '|') + 1) as newcol from t
| newcol |
| :---------- |
| 11:00-18:00 |
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.
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]
I have a query in SQL 2008
SELECT [orde_reference],
SUBSTRING([orde_reference],
CHARINDEX('/', [orde_reference]) + 1,
LEN([orde_reference])) AS batch
FROM Orders
That returns the following
orde_reference: 27777/2012/1
batch: 2012/1
However I need the batch to just be the characters after the last / (there are always 2 x '/' in the varchar
orde_reference: 27777/2012/1
batch: 1
Any help would be appreciated.
Cheers
Mim
Try
SELECT orde_reference,
RIGHT(orde_reference, CHARINDEX('/', REVERSE(orde_reference)) - 1) batch
FROM orders
Sample output:
| ORDE_REFERENCE | BATCH |
--------------------------
| 27777/2012/1 | 1 |
| 27734/2013/11 | 11 |
Here is SQLFiddle demo
As there are always 2 / you can pass the optional third argument to CHARINDEX (start_location) to tell it to start looking after the first one.
SELECT [orde_reference],
SUBSTRING([orde_reference],
CHARINDEX('/', [orde_reference],1 + CHARINDEX('/', [orde_reference])) + 1,
LEN([orde_reference])) AS batch
FROM Orders
You would be better off storing these components individually however in separate columns.
Use REVERSE twice ;)
SELECT [orde_reference]
,REVERSE(SUBSTRING(reverse([orde_reference]), 0, CHARINDEX('/', reverse([orde_reference])))) AS batch
from (values(
' 27777/2012/123'
)) as O([orde_reference])