Reputation: 31
There has been questions related to this asked, but I have not gotten the solution I am need of.
The string(s) I am trying to split up look like this:
/Dev/act/billing
or
/ST/recManage/prod/form
The issue I have is the first '/' giving me problems when I try and do things with LEFT/RIGHT/SUBSTRING/CHARINDEX. It messes up counts and stopping at the delimiter. Also, it is important to note that the number of delimiters changes. So I want to find a way to split it up so I can get every possible substring.
RIGHT(c3.Path,CHARINDEX('/', REVERSE(c3.Path))-1) AS LastPath
This has gotten me the last part of the string. I have messed with other things ilke:
SUBSTRING(c3.Path,CHARINDEX('/',c3.Path,(CHARINDEX('/',c3.Path)+1))+1,len(c3.Path)),
This gets everything after the second '/'
I have also messed with XML and
SET @delimiter='/'
;WITH CTE AS
(SELECT CAST('<M>' + REPLACE([Path], @delimiter , '</M><M>') + '</M>' AS XML)
AS [Type XML]
FROM [Rpts].[dbo].[Cata]
)
,
CTE2 as (Select [Type XML].value('/M[2]', 'varchar(50)') As FirstPath from CTE)
Then doing: CTE2.FirstPath to get the result. But this then gives NULL
I am not on SQL 2016 so I cannot use SPLIT_STRING.
Thank you
Upvotes: 3
Views: 2078
Reputation: 82010
Without going dynamic, and if you have a limited (or max) number of columns, perhaps something like this:
The replace()
in the Cross Apply assumes the strings begins with a '/'
(Easy to expand or contract ... the pattern is pretty clear)
Example
Declare @YourTable table (ID int,[Path] varchar(max))
Insert Into @YourTable values
(1,'/Dev/act/billing')
,(2,'/ST/recManage/prod/form')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + replace(substring(A.Path,2,len(A.Path)),'/','</x><x>')+'</x>' as xml) as xDim) as A
) B
Returns
EDIT - Slightly Simplified Version
Notice the staggard Pos1
and /x[2]
Select A.ID
,Pos1 = xDim.value('/x[2]','varchar(max)')
,Pos2 = xDim.value('/x[3]','varchar(max)')
,Pos3 = xDim.value('/x[4]','varchar(max)')
,Pos4 = xDim.value('/x[5]','varchar(max)')
,Pos5 = xDim.value('/x[6]','varchar(max)')
From @YourTable A
Cross Apply ( Select Cast('<x>' + replace(A.Path,'/','</x><x>')+'</x>' as xml) ) B (xDim)
Upvotes: 3
Reputation: 67341
Try this:
DECLARE @mockup TABLE(ID INT IDENTITY,YourString VARCHAR(MAX));
INSERT INTO @mockup VALUES('/Dev/act/billing'),('/ST/recManage/prod/form');
SELECT m.ID
,B.part.value(N'text()[1]',N'nvarchar(max)')
FROM @mockup AS m
OUTER APPLY(SELECT CAST('<x>' + REPLACE(m.YourString,'/','</x><x>') + '</x>' AS XML)) AS A(Casted)
OUTER APPLY A.Casted.nodes(N'/x[text()]') AS B(part);
This approach is save as long as you do not have forbidden characters in your string (namely <
, >
and &
). If you need this, just call in, it is possible to solve.
Using .nodes()
with the XQuery
predicat [text()]
will ommit all rows with no value...
The result
ID Part
---------
1 Dev
1 act
1 billing
2 ST
2 recManage
2 prod
2 form
Upvotes: 3