1

Input string -

'0|33|6|2|30|12|4|1|8|29|9|34|7|13|11|5|3|31|10|36|37|37|37|38|39|40|44|65|66'

Output string -

'0|1|2|3|4|5|6|7|8|9|10|11|12|13|29|30|31|33|34|36|37|37|37|38|39|40|44|65|66'

Need this in SQL Server 2008.

I have splitted the value on | and then inserted the values into temp table and then concatenated value. Is there any better approarch?

4
  • @BeanFrog updated the question. Commented Jan 12, 2017 at 11:52
  • 1
    Seems you have already solved the problem Commented Jan 12, 2017 at 11:59
  • 1
    CLR func will do this better than relational dbms. Commented Jan 12, 2017 at 11:59
  • Why are you trying to do this in the database? This string can't be used in other queries, so why don't you split and sort it on the client's side? Commented Jan 12, 2017 at 12:15

2 Answers 2

4

Without a Parse/Split function

Declare @String varchar(max) = '0|33|6|2|30|12|4|1|8|29|9|34|7|13|11|5|3|31|10|36|37|37|37|38|39|40|44|65|66'

Select Sorted = Stuff((Select '|' +RetVal 
                       From (
                              Select RetSeq = Row_Number() over (Order By (Select null))
                                    ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                                From  (Select x = Cast('<x>'+ replace((Select @String as [*] For XML Path('')),'|','</x><x>')+'</x>' as xml).query('.')) as A 
                                Cross Apply x.nodes('x') AS B(i)
                            ) A
                       Order By cast(RetVal as int) 
                       For XML Path ('')),1,1,'')

With a Parse/Split function'

Declare @String varchar(max) = '0|33|6|2|30|12|4|1|8|29|9|34|7|13|11|5|3|31|10|36|37|37|37|38|39|40|44|65|66'

Select Sorted = Stuff((Select '|' +RetVal 
                       From [dbo].[udf-Str-Parse-8K](@String,'|') 
                       Order By cast(RetVal as int) 
                       For XML Path ('')),1,1,'')

Both Return

0|1|2|3|4|5|6|7|8|9|10|11|12|13|29|30|31|33|34|36|37|37|37|38|39|40|44|65|66

The UDF if needed

CREATE FUNCTION [dbo].[udf-Str-Parse-8K] (@String varchar(max),@Delimiter varchar(25))
Returns Table 
As
Return (  
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)

    Select RetSeq = Row_Number() over (Order By A.N)
          ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
    From   cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
Sign up to request clarification or add additional context in comments.

Comments

2
declare @str varchar(100) =
    '0|33|6|2|30|12|4|1|8|29|9|34|7|13|11|5|3|31|10|36|37|37|37|38|39|40|44|65|66';

declare @s varchar(100) = '|' + @str + '|';
declare @result varchar(100);    

with D(d) as 
(
    select v from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) V(v)     
),
N(n) as 
(
    select top (len(@s) - 1) 
        row_number() over (order by (select 1)) from D d1, D d2
),
S(s) as
(       
    select substring(@s, n + 1, charindex('|', @s, n + 1) - (n + 1)) 
    from N where substring(@s, n, 1) = '|'
)
select top (100) @result = isnull(@result + '|', '') + s 
from S order by cast(s as int);

print @result;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.