5

I have a string such as this:

`a|b^c|d|e^f|g`

and I want to maintain the pipe delimiting, but remove the carrot sub-delimiting, only retaining the first value of that sub-delimiter.

The output result would be:

`a|b|d|e|g`

Is there a way I can do this with a simple SQL function?

3
  • which sql you want to use? Anyway, you can simply replace the ^ and the following char with empty space, since you always take the first. Commented Mar 15, 2016 at 16:35
  • Specify your RDBMS (Firebird/Teradata/MariaDB/...). Does your data contain data like a|ab^cd^ef|e^da? Commented Mar 15, 2016 at 16:35
  • I am using sql server 2005, and yes it can contain values such as a|b^c^d^e|f|g, and I want to output a|b|f|g. Basically keep anything before the ^, and get rid of everything till the next pipe. Commented Mar 15, 2016 at 16:37

3 Answers 3

3

Another option, using CHARINDEX, REPLACE and SUBSTRING:

DECLARE @OriginalString varchar(50) = 'a|b^c^d^e|f|g'

DECLARE @MyString varchar(50) = @OriginalString 

WHILE CHARINDEX('^', @MyString) > 0 
BEGIN
    SELECT @MyString = REPLACE(@MyString, 
                               SUBSTRING(@MyString, 
                                         CHARINDEX('^', @MyString), 
                                         CASE WHEN CHARINDEX('|', @MyString, CHARINDEX('^', @MyString)) > 0 THEN
                                            CHARINDEX('|', @MyString, CHARINDEX('^', @MyString)) - CHARINDEX('^', @MyString)
                                         ELSE
                                            LEN(@MyString)
                                         END
                                         )
                       , '')
END

SELECT @OriginalString As Original, @MyString As Final

Output:

Original              Final
a|b^c^d^e|f|g         a|b|f|g
Sign up to request clarification or add additional context in comments.

8 Comments

@kunkel1 Hate to tell you this is an infinite loop when there's no pipe after the final caret.
Edited my answer to handle the case when the string is not closed with a pipe (|)
@shawnt00 After reading your answer I tested and edited mine. I have to admit your solution is probably better, though. upvoted your answer.
@shawnt00 "I suspect that reputation often sways OPs": uh, yeah ;-). Well, voters in general. It's one of the main down-sides to listing rep on anything but a user's profile page. It makes it too easy to gain implicit trust such that sometimes voters don't even bother checking the answer before up-voting (though I am not implying that this answer should not have gotten any votes, I am just pointing out a behavior that I have noticed).
I appreciate all of the help. I picked the top answer based on which one I could plug in and make work in my application with my limited SQL knowledge. I couldn't get the other two to work (most likely my fault). Thanks for following up with the modification. My test values did not have this situation, but it could have been bad to have left it, so I made the correction and everything looks great. :)
|
2

This expression will replace the first instance of caret up to the subsequent pipe (or end of string.) You can just run a loop until no more rows are updated or no more carets are found inside the function, etc.

case
    when charindex('^', s) > 0
    then stuff(
             s,
             charindex('^', s),
             charindex('|', s + '|', charindex('^', s) + 1) - charindex('^', s),
             ''
         )
    else s
end

Here's a loop you can adapt for a function definition:

declare @s varchar(30) = 'a|b^c^d|e|f^g|h^i';
declare @n int = charindex('^', @s);

while @n > 0
begin
    set @s = stuff(@s, @n, charindex('|', @s + '|', @n + 1) - @n, '');
    set @n = charindex('^', @s, @n + 1);
end
select @s;

A little bit of care needs to be taken for the trailing of the string where there won't be a final pipe separator. You can see I've handled that.

Comments

2

First split the values delimited by | then extract the first value and concatenate the result back to get the result

Try this

SELECT Cast(left(intr,len(intr)-1) AS VARCHAR(1000)) AS res
FROM   (SELECT LEFT(split_val, Isnull(NULLIF(Charindex('^', split_val), 0)-1, Len(split_val))) + '|'
        FROM   Udf_splitstring('a|bdd^c|d|e^f|g', '|')
        FOR xml path (''))a (intr) 

Result : a|bdd|d|e|g

Here is a article about split string functions Split strings the right way – or the next best way

4 Comments

You're assuming the values are going to be single characters.
what if the original string is |xb^dfg|b|f^df|? this answer will return |x|b|f|, instead of |xb|b|f|...
@shawnt00 - Yeah becoz of sample data, check now updated
@ZoharPeled - Updated my answer

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.