January 19, 2015 at 9:52 pm
Hi everyone i want split the data this below format..
1.Split the RR ("PL:TW RR:1.8%,PL:TX RR:0.9%") into LowendRR ("PL:TW RR:1.8%") and HighendRR ("PL:TX RR:0.9%")
2.Split the LowendRR ("PL:TW RR:1.8%") into LowendPL ("TW"), LowendPLValues ("1.8%")
3.Split the HighendRR ("PL:TX RR:0.9%") into HighendPL ("TX"), HighendPLValues ("0.9%")
using charindex,substrings am waiting for reply..:-)
January 20, 2015 at 12:54 am
You should create a function but I just copy pasted to work out each one
DECLARE @RR nvarchar(256)
, @LowendRR nvarchar(256)
, @HighendRR nvarchar(256)
, @LowendPL nvarchar(256)
, @HighendPL nvarchar(256)
, @LowendPLvalues nvarchar(256)
, @HighendPLvalues nvarchar(256)
, @SplitChar nchar(1)
SET @SplitChar = ','
SET @RR = 'PL:TW RR:1.8%,PL:TX RR:0.9%'
SELECT @LowendRR = substring(@RR,1,charindex(@SplitChar,@RR,0) - 1)
, @HighendRR = substring(@RR,charindex(@SplitChar,@RR,0) + 1, len(@RR) - charindex(@SplitChar,@RR,0))
SELECT @LowendRR LowendRR, @HighendRR HighendRR
/*First split on space*/
SET @SplitChar = ' '
SELECT @LowendPL = substring(@LowendRR,1,charindex(@SplitChar,@LowendRR,0) - 1)
, @HighendPL = substring(@HighendRR,1,charindex(@SplitChar,@HighendRR,0) - 1)
, @LowendPLvalues = substring(@LowendRR, charindex(@SplitChar,@LowendRR ,0) + 1, len(@LowendRR) - charindex(@SplitChar,@LowendRR ,0))
, @HighendPLvalues = substring(@HighendRR,charindex(@SplitChar,@HighendRR,0) + 1, len(@HighendRR) - charindex(@SplitChar,@HighendRR,0))
--SELECT @LowendPL LowendPL, @LowendPLvalues LowendPLvalues, @HighendPL HighendPL, @HighendPLvalues HighendPLvalues
/*2nd split on :*/
SET @SplitChar = ':'
SELECT @LowendPL = substring(@LowendPL, charindex(@SplitChar,@LowendPL ,0) + 1, len(@LowendPL) - charindex(@SplitChar,@LowendPL ,0))
, @HighendPL = substring(@HighendPL,charindex(@SplitChar,@HighendPL,0) + 1, len(@HighendPL) - charindex(@SplitChar,@HighendPL,0))
, @LowendPLvalues = substring(@LowendPLvalues, charindex(@SplitChar,@LowendPLvalues ,0) + 1, len(@LowendPLvalues) - charindex(@SplitChar,@LowendPLvalues ,0))
, @HighendPLvalues = substring(@HighendPLvalues,charindex(@SplitChar,@HighendPLvalues,0) + 1, len(@HighendPLvalues) - charindex(@SplitChar,@HighendPLvalues,0))
/*Final values*/
SELECT @LowendPL LowendPL, @LowendPLvalues LowendPLvalues, @HighendPL HighendPL, @HighendPLvalues HighendPLvalues
January 20, 2015 at 1:32 am
WITH SampleData (RR) AS
(
SELECT 'PL:TW RR:1.8%,PL:TX RR:0.9%'
)
SELECT LowendRR, HighendRR
,LowendPL = RIGHT(ls, CHARINDEX(':', REVERSE(ls))-1)
,LowendPLValues = RIGHT(LowendRR, CHARINDEX(':', REVERSE(LowendRR))-1)
,HighendPL = RIGHT(rs, CHARINDEX(':', REVERSE(rs))-1)
,HighendPLValues = RIGHT(HighendRR, CHARINDEX(':', REVERSE(HighendRR))-1)
FROM SampleData a
CROSS APPLY (SELECT cp = CHARINDEX(',', RR)) b
CROSS APPLY
(
SELECT LowendRR = LEFT(RR, cp-1), HighendRR=SUBSTRING(RR, cp+1, 99)
) c
CROSS APPLY
(
SELECT ls = LEFT(LowendRR, CHARINDEX(' ', LowendRR)-1)
,rs = LEFT(HighendRR, CHARINDEX(' ', HighendRR)-1)
) d;
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
January 21, 2015 at 1:47 am
Quick solution using the DelimitedSplit8K[/url] function
😎
USE tempdb;
GO
SET NOCOUNT ON;
DECLARE @SAMPLE_DATA TABLE
(
SD_TEXT VARCHAR(100) NOT NULL
);
INSERT INTO @SAMPLE_DATA (SD_TEXT)
VALUES ('PL:TW RR:1.8%,PL:TX RR:0.9%')
;
;WITH FIRST_SPLIT AS
(
SELECT
C.ItemNumber
,C.Item
FROM @SAMPLE_DATA SD
OUTER APPLY dbo.DelimitedSplit8K(SD.SD_TEXT,CHAR(44)) AS C
)
,SECOND_SPLIT AS
(
SELECT
FS.ItemNumber AS PARENT_ID
,S.ItemNumber AS ITEM_ID
,S.Item AS ITEM
FROM FIRST_SPLIT FS
OUTER APPLY dbo.DelimitedSplit8K(FS.Item,CHAR(32)) AS S
)
SELECT
SP.PARENT_ID
,SP.ITEM_ID
,X.ItemNumber AS VALUE_ID
,X.Item AS VALUE
FROM SECOND_SPLIT SP
OUTER APPLY dbo.DelimitedSplit8K(SP.ITEM,CHAR(58)) AS X
;
Results
PARENT_ID ITEM_ID VALUE_ID VALUE
---------- -------- --------- ------
1 1 1 PL
1 1 2 TW
2 1 1 PL
2 1 2 TX
2 2 1 RR
2 2 2 0.9%
1 2 1 RR
1 2 2 1.8%
January 22, 2015 at 3:20 pm
Your string can be turned into valid XML with three REPLACE functions, then you can use XML functions to do all the parsing. Assuming none of the possible RR values might contain characters like ", <, >, or &.
DECLARE @input VARCHAR(100) = 'PL:TW RR:1.8%,PL:TX RR:0.9%';
DECLARE @PL XML = '<PL>' + REPLACE(REPLACE(REPLACE(@input + ',', 'PL:', '<'), ':', '="'), ',', '" />') + '</PL>';
SELECT @PL;
-- Get all values as a table
SELECT param = v.value('local-name(.)', 'varchar(50)'),
value = v.value('./@RR', 'varchar(50)')
FROM @PL.nodes('/PL/*') p(v)
-- Unpivot that table to get individual values in one row
-- Assuming TW and TX are not the only possible names
SELECT TW = MAX(CASE param WHEN 'TW' THEN value END),
TX = MAX(CASE param WHEN 'TX' THEN value END),
Fred = MAX(CASE param WHEN 'AA' THEN value END),
Barney = MAX(CASE param WHEN 'ZZ' THEN value END)
FROM (
SELECT param = v.value('local-name(.)', 'varchar(50)'),
value = v.value('./@RR', 'varchar(50)')
FROM @PL.nodes('/PL/*') p(v)
) PL
January 22, 2015 at 10:33 pm
Scott Coleman (1/22/2015)
Your string can be turned into valid XML with three REPLACE functions, then you can use XML functions to do all the parsing. Assuming none of the possible RR values might contain characters like ", <, >, or &.
DECLARE @input VARCHAR(100) = 'PL:TW RR:1.8%,PL:TX RR:0.9%';
DECLARE @PL XML = '<PL>' + REPLACE(REPLACE(REPLACE(@input + ',', 'PL:', '<'), ':', '="'), ',', '" />') + '</PL>';
SELECT @PL;
-- Get all values as a table
SELECT param = v.value('local-name(.)', 'varchar(50)'),
value = v.value('./@RR', 'varchar(50)')
FROM @PL.nodes('/PL/*') p(v)
-- Unpivot that table to get individual values in one row
-- Assuming TW and TX are not the only possible names
SELECT TW = MAX(CASE param WHEN 'TW' THEN value END),
TX = MAX(CASE param WHEN 'TX' THEN value END),
Fred = MAX(CASE param WHEN 'AA' THEN value END),
Barney = MAX(CASE param WHEN 'ZZ' THEN value END)
FROM (
SELECT param = v.value('local-name(.)', 'varchar(50)'),
value = v.value('./@RR', 'varchar(50)')
FROM @PL.nodes('/PL/*') p(v)
) PL
Oh, careful, Scott. The concatenation will absolutely crush performance here. It takes turns beating and losing to a While loop. Here's a picture of some massive testing previously done...
Here's the article that picture came from.
http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Jeff Moden
Change is inevitable... Change for the better is not.
January 23, 2015 at 1:58 pm
With you around here Jeff, I figured it wasn't up to me to post another article comparing all possible string splitting techniques. I've enjoyed your articles on string splitting, and most of my servers are already infested with tally tables. Just before reading your response I actually gave some tally table code to a colleague with a new server who needed to split strings.
But this seemed to be a question about a very constrained range of short strings. The XML solution popped into my head so I posted it without a detailed performance analysis. I think there is some value in having XML queries among your bag of tricks, but it is very true that you need to be wary of the overhead involved.
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply