I have a view where I would like to create a column that isolates a string between 3 of the same character ("-"). So for example, I want AC-RBQ/4110-WS-L1 to become RBQ/4110.
So far I have tried this and it gets me very close.
SELECT SUBSTRING(locnum,CHARINDEX('-',locnum)+1,(((LEN(locnum))-CHARINDEX('-', REVERSE(locnum)))-CHARINDEX('-',locnum))) AS Result
Result:
RBQ/4110-WS
RBQ/4110-CS
I just need to remove that last "-WS" or "-CS"
Any thoughts or ideas would be greatly appreciated!
If the pattern is consistent, perhaps parsename() would be a good fit here
Example
Declare #S varchar(100) = 'AC-RBQ/4110-WS-L1'
Select parsename(replace(#S,'-','.'),3)
Returns
RBQ/4110
EDIT -
Just in case your data is more variable, you can use XML to extract the SECOND value
Example
Declare #YourTable table (locnum varchar(100))
Insert Into #YourTable values
('AC-RBQ/4110-WS-L1')
Select NewValue = convert(xml,'<x>'+replace(locnum,'-','</x><x>')+'</x>').value('/x[2]','varchar(100)')
From #YourTable
Returns
NewValue
RBQ/4110
It would seem simpler to split the value and then extract the 2nd item from your data. If your data always has 4 elements (and you always need the second), you could use PARSENAME:
SELECT PN.P
FROM (VALUES('AC-RBQ/4110-WS-L1'))V(S)
CROSS APPLY (VALUES(PARSENAME(REPLACE(V.S,'-','.'),3)))PN(P); --Part 3 as PARSENAME works right to left
Otherwise you could use a splitter like delimitedsplit8k_lead:
SELECT DS.Item
FROM (VALUES('AC-RBQ/4110-WS-L1'))V(S)
CROSS APPLY dbo.DelimitedSplit8K_lead(V.S,'-') DS
WHERE DS.ItemNumber = 2;
Please Try below Query. If your pattern is same per your question then below will work.
select left(SUBSTRING('AC-RBQ/4110-WS-L1', charindex('-','AC-RBQ/4110-WS-L1') + 1, LEN('AC-RBQ/4110-WS-L1')),8)
WITH TEMP AS
(
SELECT 'AC-RBQ/4110-WS-L1' AS COL
)
SELECT * ,
CHARINDEX('-', [COL]) AS FR,
CHARINDEX('-', [COL],CHARINDEX('-', [COL])+1) AS FR2,
SUBSTRING([COL], CHARINDEX('-', [COL]) +1 ,CHARINDEX('-', [COL],CHARINDEX('-
', [COL])+1) - (CHARINDEX('-', [COL]) +1) ) AS RESULT
FROM TEMP
You've done most of the work and you need to get the left part of the result up to -:
SELECT
LEFT(SUBSTRING(locnum, CHARINDEX('-', locnum) + 1,
(((LEN(locnum)) - CHARINDEX('-', REVERSE(locnum))) - CHARINDEX('-', locnum))),
CHARINDEX('-', SUBSTRING(locnum, CHARINDEX('-', locnum) + 1,
(((LEN(locnum)) - CHARINDEX('-', REVERSE(locnum))) - CHARINDEX('-', locnum)))) - 1) AS Result
Related
In one of the column i am getting 2 values with a delimiter between it
How to extract both the values
I have some thing like this Column TRN02 is 115679-5757
I need to take values before delimiter and after delimter into 2 separate columns again.
Can some one help me on this
You can use SUBSTRING to do this:
SELECT
SUBSTRING(TRN02, 0, CHARINDEX('-', TRN02)) AS [First]
SUBSTRING(TRN02, CHARINDEX('-', TRN02) + 1, LEN(TRN02)) AS [Second]
FROM TABLE
Just another way USING LEFT and RIGHT -
SELECT LEFT(TRN02, CHARINDEX('-', TRN02) - 1) [before_delim],
RIGHT(TRN02, LEN(TRN02) - CHARINDEX('-', TRN02)) [after_delim]
FROM your_table
SELECT LEFT(details, CHARINDEX ('-', TRN02 ) - 1),
SUBSTRING(details, CHARINDEX ('-', TRN02 ) + 1, 100)
FROM Your_table
update df set df.column=s.[value] FROM table df
cross APPLY string_split(REPLACE(column, 'split_parameter', '#') ,'#') s
where column like '%split_parameter%' and s.[value] not like '=%'
I'm trying to create a stored procedure for updating a table in a batch. I want to take parameters in as a nvarchar and call string_split on them.
#ParamList1 NVARCHAR(max) = '1,2,3,4,5'
#ParamList2 NVARCHAR(max) = 'a,b,c,d,e'
I want to get a temporary table like
Param1 Param2
1 a
2 b
3 c
...
How would I do this?
Unfortunately, string_split() does not guarantee ordering or provide a position argument (Microsoft are you listening?).
So, the safest method is a recursive CTE (or perhaps another approach using XML):
with cte as (
select convert(nvarchar(max), NULL) as x1, convert(nvarchar(max), NULL) as x2, #paramlist1 as rest1, #paramlist2 as rest2, 1 as lev
union all
select convert(nvarchar(max), left(rest1, charindex(',', rest1 + ',') - 1)),
convert(nvarchar(max), left(rest2, charindex(',', rest2 + ',') - 1)),
stuff(rest1, 1, charindex(',', rest1 + ','), ''),
stuff(rest2, 1, charindex(',', rest2 + ','), ''),
lev + 1
from cte
where rest1 <> '' and rest2 <> ''
)
select *
from cte
where x1 is not null;
Here is a db<>fiddle.
You've got an answer already, which is working fine, but this should be faster and easier:
You did not specify your SQL-Server's version, but - talking about STRING_SPLIT() - I assume it's at least v2016. If this is correct, you can use OPENJSON. Your list of numbers needs nothing more than brackets to be a JSON-array ([1,2,3]), while an array of words/letters can be transformed with some easy string operations (["a","b","c"]).
Following the docs, OPENJSON returns the elements position in [key], while the element itself is returned in [value]. You can simply JOIN these sets:
DECLARE #ParamList1 NVARCHAR(max) = '1,2,3,4,5';
DECLARE #ParamList2 NVARCHAR(max) = 'a,b,c,d,e';
SELECT p1.[key] AS FragmentNr
,p1.[value] AS P1
,p2.[value] AS P2
FROM OPENJSON(CONCAT('[',#ParamList1 + ']')) p1
INNER JOIN OPENJSON(CONCAT('["',REPLACE(#ParamList2,',','","'),'"]')) p2 ON p1.[key]=p2.[key] ;
In this answer you will find some details (UPDATE section 1 and 2).
I am trying to reverse string values in a column in SQL Server.
What I am trying to achieve is, when the value of the column is child/parent, I want to change it to parent/child when child contains '112'
For example I want to change columns with value Reports/112-Major to 112-Major/Reports
To start with, I tried to use STRING_SPLIT and append them like String_Split(ColumnName,'/')[1] + String_Split(ColumnName,'/')[0] if String_Split(ColumnName,'/')[1] like '%112%'
Most of the examples that I see online have something like
SELECT Value FROM STRING_SPLIT('Lorem/ipsum/dolor/sit/amet.', '/');
But I want to split and then merge based on condition and then update the column
Something like,
update tblTableName
set siteUrl = String_Split(ColumnName,'/')[1] + String_Split(ColumnName,'/')[0]
where `String_Split(ColumnName,'/')[1] like '%112%'
Is there a way to do this in SQL Server?
You can use this expression:
stuff(col, 1, charindex('/', col), '') + '/' + left(col, charindex('/', col) - 1)
Another option just for fun.
Gordon's solution would be my first choice and is certainly more performant (+1), but the following illustrates a simple technique which can be used to split a string into columns and not rows.
Sample
Declare #YourTable table (ID int,YourCol varchar(100))
Insert Into #YourTable values
(1,'Reports/112-Major'),
(2,'Reports/Something Else')
Update #YourTable Set YourCol = Pos2+'/'+Pos1
From #YourTable A
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
From (Select Cast('<x>' + replace((Select replace(A.YourCol,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as B1
) B
Where Pos2 Like '%112%'
Updated Results
ID YourCol
1 112-Major/Reports
2 Reports/Something Else
I have this data in my column:
32-HC-100-10001-G03P2-N-1-1001
The problem is my value doesn't have a fixed length. What I need to do is split this value into 2 columns 32-HC-100-10001-G03P2-N and 1 - the numbers after last - don't important
Another example
4-G-100-10029-F23S-S-2-1001
should be split into 4-G-100-10029-F23S-S and 2. I have used SUBSTRING([Line No#], 0, 21) but because of the length it didn't work.
Try this way
declare #str varchar(100)=reverse('4-G-100-10029-F23S-S-2-1001')
select reverse(substring(#str,charindex('-',#str)+1,len(#str))) as first_col,
left(substring(#str,charindex('-',#str)+1,len(#str)),charindex('-',substring(#str,charindex('-',#str)+1,len(#str)))-1) as second_col
May not be the shortest method but should get the job done
Note : I did not hard-code any length here
As long as the last part(1-1001,2-2002...) have the same number of values,this will work..
declare #string varchar(max)
set #string='32-HC-100-10001-G03P2-N-1-1001'
select replace(#string, right(#string,7),''),substring(right(#string,6),1,1)
Output:
32-HC-100-10001-G03P2-N 1
When doing complex string operations in SQL Server, one method uses outer apply to simplify the calculations:
select t.col, s2.firstpart, s2.secondpart
from t outer apply
(select left(col, len(col) - charindex('-', reverse(col)) as s1
-- remove the last number
) s1 outer apply
(select left(s1, len(s1) - charindex('-', reverse(s1)) as firstpart,
right(s1, charindex('-', reverse(s1)) -1) as secondpart
) s2;
I find the calculations easier to construct, follow, and debug.
You can try this:
DECLARE #string nvarchar(max) = '32-HC-100-10001-G03P2-N-1-1001'
SELECT REVERSE(STUFF(SUBSTRING(REVERSE(#string),CHARINDEX('-',REVERSE(#string))+1,LEN(#string)),1,CHARINDEX('-',SUBSTRING(REVERSE(#string),CHARINDEX('-',REVERSE(#string))+1,LEN(#string))),'')),
REVERSE(LEFT(SUBSTRING(REVERSE(#string),CHARINDEX('-',REVERSE(#string))+1,LEN(#string)),CHARINDEX('-',SUBSTRING(REVERSE(#string),CHARINDEX('-',REVERSE(#string)),LEN(#string)))))
Output:
32-HC-100-10001-G03P2-N 1
If it is always comes as a 7th part you can use XML:
DECLARE #string nvarchar(max) = '32-HC-100-10001-G03P2-N-1-1001',
#xml xml
SELECT #xml = CAST('<d>'+REPLACE(#string,'-','</d><d>') +'</d>' as xml)
SELECT t.v.value('/d[1]','nvarchar(10)') + '-' +
t.v.value('/d[2]','nvarchar(10)') + '-' +
t.v.value('/d[3]','nvarchar(10)') + '-' +
t.v.value('/d[4]','nvarchar(10)') + '-' +
t.v.value('/d[5]','nvarchar(10)') + '-' +
t.v.value('/d[6]','nvarchar(10)'),
t.v.value('/d[7]','nvarchar(10)')
FROM #xml.nodes('/') as t(v)
Output:
32-HC-100-10001-G03P2-N 1
In one of the column i am getting 2 values with a delimiter between it
How to extract both the values
I have some thing like this Column TRN02 is 115679-5757
I need to take values before delimiter and after delimter into 2 separate columns again.
Can some one help me on this
You can use SUBSTRING to do this:
SELECT
SUBSTRING(TRN02, 0, CHARINDEX('-', TRN02)) AS [First]
SUBSTRING(TRN02, CHARINDEX('-', TRN02) + 1, LEN(TRN02)) AS [Second]
FROM TABLE
Just another way USING LEFT and RIGHT -
SELECT LEFT(TRN02, CHARINDEX('-', TRN02) - 1) [before_delim],
RIGHT(TRN02, LEN(TRN02) - CHARINDEX('-', TRN02)) [after_delim]
FROM your_table
SELECT LEFT(details, CHARINDEX ('-', TRN02 ) - 1),
SUBSTRING(details, CHARINDEX ('-', TRN02 ) + 1, 100)
FROM Your_table
update df set df.column=s.[value] FROM table df
cross APPLY string_split(REPLACE(column, 'split_parameter', '#') ,'#') s
where column like '%split_parameter%' and s.[value] not like '=%'