3
\$\begingroup\$

I wrote an SQL Server function which returns the substring before the Nth occurrence of a character.

For example:

SELECT dbo.fn_getFirstNthSentence('.', 'hello world.It.is.raining.today', 3)

returns 'hello world.It.Is.' as a result.

The function I wrote looks dirty and slow so I want to optimize it. Any advice to make it clean is appreciated.

CREATE FUNCTION fn_getFirstNthSentence
(
 @TargetStr VARCHAR(MAX) ,
 @SearchedStr VARCHAR(8000) ,
 @Occurrence INT
)
RETURNS varchar(MAX)
AS
BEGIN
 DECLARE @pos INT ,
 @counter INT ,
 @ret INT;
 SET @pos = CHARINDEX(@TargetStr, @SearchedStr);
 IF ( @pos = 0 )
 RETURN @SearchedStr
 SET @counter = 1;
 IF @Occurrence = 1
 SET @ret = @pos;
 ELSE
 BEGIN
 WHILE ( @counter < @Occurrence )
 BEGIN
 IF(LEN(@SearchedStr) < @pos + 1)
 RETURN @SearchedStr
 SELECT @ret = CHARINDEX(@TargetStr, @SearchedStr,
 @pos + 1);
 IF(@ret = 0)
 RETURN @SearchedStr
 SET @counter = @counter + 1;
 SET @pos = @ret;
 END;
 END;
 RETURN LEFT(@SearchedStr, @ret)
END;
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 29, 2016 at 13:52
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

It's not necessary to set the return string @ret all the time. You can first look for occurrences of @TargetStr with an incrementing start_location parameter of the CHARINDEX function. Only after no (new) occurrences are found, or when the required max number of occurrences are found is it time to set the return string:

CREATE FUNCTION fn_getFirstNthSentence
(
 @TargetStr VARCHAR(MAX) ,
 @SearchedStr VARCHAR(8000) ,
 @Occurrence INT
)
RETURNS varchar(MAX)
AS
BEGIN
 DECLARE @counter INT = 0
 , @index INT = 0
 , @newIndex INT
 , @end BIT = 0;
 WHILE(@end = 0 AND @counter < @occurrence)
 BEGIN
 SET @counter = @counter + 1;
 SET @newIndex = CHARINDEX(@TargetStr, @SearchedStr, @index + 1);
 IF (@newIndex > 0)
 SET @index = @newIndex;
 ELSE
 SET @end = 1;
 END
 IF @index > 0 SET @index = @index - 1;
 RETURN LEFT(@SearchedStr, @index)
END

Note that this returns an empty string if no occurrences are found. I think that's more correct for a function that returns "everything until the nth occurrence of x".

answered Jul 29, 2016 at 23:01
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.