August 6, 2014 at 2:13 pm
I have a two column ID and Path that contains below information. I have almost 1000 records but I just put 3 here for example.
ID Path
1./ACS/OTHER ACS REPORTS/XYZ/ABC
2./ACS/OTHER ACS REPORTS/Pending Deletion(JJP)
3./ACS/Pending Deletion(JJP)
I want to create each new column based on "/".
I want
1. ACS Other ACS reports XYZ ABC
2. ACS Others ACS reports Pending deletion (JJP)
3. ACS Pending Deletion (JJP)
I am getting 5 column and Path column split into 4 extra column (see record 1)
and second split into 3 column based on "/" and third split into 2 column based "/".
I have almost 1000 rows and I need to split by subfolder.
Can any one help me ?
Thanks
Bhavesh
August 7, 2014 at 6:38 am
Is there any one can help ??
August 7, 2014 at 7:25 am
patla4u (8/7/2014)
Is there any one can help ??
Hey there!
It'd be great if you could have a read of this (http://www.sqlservercentral.com/articles/Best+Practices/61537/)[/url], then set up some sample data, DDL and expected results based on your sample data. Otherwise, you're asking the unpaid volunteers of this site to do this for you so that they can provide you with a working, tested solution.
I've had a quick go, using the 8K Delimited Splitter[/url].
So first, you need this function: -
IF EXISTS ( SELECT 1
FROM sys.[objects]
WHERE [name] = 'DelimitedSplit8K'
AND type = 'IF' )
BEGIN;
DROP FUNCTION [dbo].[DelimitedSplit8K];
END;
GO
CREATE FUNCTION [dbo].[DelimitedSplit8K]
--===== Define I/O parameters
(@pString VARCHAR(8000), @pDelimiter CHAR(1))
--WARNING!!! DO NOT USE MAX DATA-TYPES HERE! IT WILL KILL PERFORMANCE!
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000...
-- enough to cover VARCHAR(8000)
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
-- for both a performance gain and prevention of accidental "overruns"
SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
SELECT s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
FROM cteStart s
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
;
GO
Now, here's some sample data: -
-- CREATE SAMPLE DATA
IF object_id('tempdb..#testEnvironment') IS NOT NULL
BEGIN;
DROP TABLE #testEnvironment;
END;
SELECT [ID], [Path]
INTO #testEnvironment
FROM (VALUES(1,'./ACS/OTHER ACS REPORTS/XYZ/ABC'),
(2,'./ACS/OTHER ACS REPORTS/Pending Deletion(JJP)'),
(3,'./ACS/Pending Deletion(JJP)')
)a([ID], [Path]);
Now, assuming that it is only ever 5 deep, we could do this: -
SELECT ID,
MAX(CASE WHEN ItemNumber = 1 THEN Item ELSE '' END) AS [1],
MAX(CASE WHEN ItemNumber = 2 THEN Item ELSE '' END) AS [2],
MAX(CASE WHEN ItemNumber = 3 THEN Item ELSE '' END) AS [3],
MAX(CASE WHEN ItemNumber = 4 THEN Item ELSE '' END) AS [4],
MAX(CASE WHEN ItemNumber = 5 THEN Item ELSE '' END) AS [5]
FROM [#testEnvironment] AS te
CROSS APPLY [dbo].[DelimitedSplit8K](te.[Path], '/') AS de
GROUP BY ID;
Which returns: -
ID 1 2 3 4 5
----------- ---- ---- ---------------------- ---------------- ----
1 . ACS OTHER ACS REPORTS XYZ ABC
2 . ACS OTHER ACS REPORTS Pending Deletion
3 . ACS Pending Deletion(JJP)
That assumes that you want to return the root ".", do you actually want that bit? It also assumes that you only ever have 5 deep in your structure, we can make this "any level" using dynamic SQL if required, but without more information from you it seemed pointless to do so now.
Does that give you a starting point for getting a working solution?
August 7, 2014 at 7:39 am
If I understood your question correctly, this is likely also a solution you might consider -> Converting a delimited string of values into columns
(If not it's at least a great read)
;WITH CTE (strval)
AS
(
SELECT CONVERT(xml, '<col>' + REPLACE('/ACS/OTHER ACS REPORTS/XYZ/ABC', '/', '</col><col>') + '</col>')
)
SELECTstrval.value(('/col[2]'), 'varchar(128)') 'Firstcol',
strval.value(('/col[3]'), 'varchar(128)') 'Secondol',
strval.value(('/col[4]'), 'varchar(128)') 'Thirdcol',
strval.value(('/col[5]'), 'varchar(128)') 'Fourthcol'
FROMCTE;
August 7, 2014 at 7:42 am
Sebastian Zeller (8/7/2014)
If I understood your question correctly, this is likely also a solution you might consider -> Converting a delimited string of values into columns(If not it's at least a great read)
Take a read through the 8K Delimited Splitter article[/url] and you'll see that XML splitters are significantly slower than the one I used in the solution above.
August 7, 2014 at 8:02 am
Cadavre (8/7/2014)
Sebastian Zeller (8/7/2014)
If I understood your question correctly, this is likely also a solution you might consider -> Converting a delimited string of values into columns(If not it's at least a great read)
Take a read through the 8K Delimited Splitter article[/url] and you'll see that XML splitters are significantly slower than the one I used in the solution above.
I didn't intend to challenge or even downgrade your solution. The sole purpose was to show the OP another possible way of doing it 🙂
August 7, 2014 at 8:04 am
Sebastian Zeller (8/7/2014)
Cadavre (8/7/2014)
Sebastian Zeller (8/7/2014)
If I understood your question correctly, this is likely also a solution you might consider -> Converting a delimited string of values into columns(If not it's at least a great read)
Take a read through the 8K Delimited Splitter article[/url] and you'll see that XML splitters are significantly slower than the one I used in the solution above.
I didn't intend to challenge or even downgrade your solution. The sole purpose was to show the OP another possible way of doing it 🙂
I know. . . I was just pointing you at the resource with test results that shows XML splitters are slower than the 8k splitter.
August 7, 2014 at 10:54 am
Thanks for your reply.
But
SELECT
ID,
MAX(CASE WHEN ItemNumber = 1 THEN Item ELSE '' END) AS [1],
MAX(CASE WHEN ItemNumber = 2 THEN Item ELSE '' END) AS [2],
MAX(CASE WHEN ItemNumber = 3 THEN Item ELSE '' END) AS [3],
MAX(CASE WHEN ItemNumber = 4 THEN Item ELSE '' END) AS [4],
MAX(CASE WHEN ItemNumber = 5 THEN Item ELSE '' END) AS [5]
FROM
#testEnvironment AS AB
CROSS APPLY
dbo.[DelimitedSplit8K](AB.path, '/') AS de
GROUP BY ID;
is not working for me.
I am getting
Error msg : Msg 102, Level 15, State 1, Line 11
Incorrect syntax near '.'.
When I ran below
SELECT
ID,
MAX(CASE WHEN ItemNumber = 1 THEN Item ELSE '' END) AS [1],
MAX(CASE WHEN ItemNumber = 2 THEN Item ELSE '' END) AS [2],
MAX(CASE WHEN ItemNumber = 3 THEN Item ELSE '' END) AS [3],
MAX(CASE WHEN ItemNumber = 4 THEN Item ELSE '' END) AS [4],
MAX(CASE WHEN ItemNumber = 5 THEN Item ELSE '' END) AS [5]
FROM
#testEnvironment AS AB
CROSS APPLY
dbo.[DelimitedSplit8K]('./ACS/OTHER ACS REPORTS/XYZ/ABC', '/') AS de
GROUP BY ID;
This is run perfectly.
How can we resolve error msg
Error msg : Msg 102, Level 15, State 1, Line 11
Incorrect syntax near '.'.
?
August 7, 2014 at 11:05 pm
What data type is path?
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply