Search code examples
sql-servert-sqlreporting-servicessplitcharindex

Splitting a dynamic string


I need help parsing a dynamic string(see below). This string can change to only have one set of values to two, to three(like the one below).

Raw String:

valueA=valueB=valueC=valueD==valueE&valueA=valueB=valueC=valueD==valueE&valueA=valueB=valueC=valueD==valueE

End Result: VelueB, ValueB, ValueB

I have been able to extract valueA using the STUFF and CHARINDEX function(see below) but I'm having difficulty just getting valueB. I have also tried doing it in ssrs using the split function but getting nowhere.

STUFF(( SELECT  ',' + ' ' + SUBSTRING(param, 1,
                                              CHARINDEX('=', param) - 1)
                FROM    dbo.Fn_mvparam(column_a, '&') AS fm
              FOR
                XML PATH('')
              ), 1, 1, ' ')

Solution

  • This should do the trick for you. Hope its useful to you

    CREATE FUNCTION uft_DoubleSplitter 
    (   
        -- Add the parameters for the function here
        @String VARCHAR(4000), 
        @Splitter1 CHAR,
        @Splitter2 CHAR
    )
    RETURNS @Result TABLE (Id INT,MId INT,SValue VARCHAR(4000))
    AS
    BEGIN
    DECLARE @FResult TABLE(Id INT IDENTITY(1, 1),
                       SValue VARCHAR(4000))
    DECLARE @SResult TABLE(Id INT IDENTITY(1, 1),
                       MId INT,
                       SValue VARCHAR(4000))
    SET @String = @String+@Splitter1
    
    WHILE CHARINDEX(@Splitter1, @String) > 0
        BEGIN
           DECLARE @WorkingString VARCHAR(4000) = NULL
    
           SET @WorkingString = SUBSTRING(@String, 1, CHARINDEX(@Splitter1, @String) - 1)
           --Print @workingString
    
           INSERT INTO @FResult
           SELECT CASE
                WHEN @WorkingString = '' THEN NULL
                ELSE @WorkingString
                END
    
           SET @String = SUBSTRING(@String, LEN(@WorkingString) + 2, LEN(@String))
    
        END
    IF ISNULL(@Splitter2, '') != ''
        BEGIN
           DECLARE @OStartLoop INT
           DECLARE @OEndLoop INT
    
           SELECT @OStartLoop = MIN(Id),
                @OEndLoop = MAX(Id)
           FROM @FResult
    
           WHILE @OStartLoop <= @OEndLoop
              BEGIN
                 DECLARE @iString VARCHAR(4000)
                 DECLARE @iMId INT
    
                 SELECT @iString = SValue+@Splitter2,
                       @iMId = Id
                 FROM @FResult
                 WHERE Id = @OStartLoop
    
                 WHILE CHARINDEX(@Splitter2, @iString) > 0
                    BEGIN
                        DECLARE @iWorkingString VARCHAR(4000) = NULL
    
                        SET @IWorkingString = SUBSTRING(@iString, 1, CHARINDEX(@Splitter2, @iString) - 1)
    
                        INSERT INTO @SResult
                        SELECT @iMId,
                             CASE
                             WHEN @iWorkingString = '' THEN NULL
                             ELSE @iWorkingString
                             END
    
                        SET @iString = SUBSTRING(@iString, LEN(@iWorkingString) + 2, LEN(@iString))
    
                    END
    
                 SET @OStartLoop = @OStartLoop + 1
              END
           INSERT INTO @Result
           SELECT MId AS PrimarySplitID,
                ROW_NUMBER() OVER (PARTITION BY MId ORDER BY Mid, Id) AS SecondarySplitID ,
                SValue
           FROM @SResult
        END
    ELSE
        BEGIN
           INSERT INTO @Result
           SELECT Id AS PrimarySplitID,
                NULL AS SecondarySplitID,
                SValue
           FROM @FResult
        END
    RETURN
    

    Usage:

    --FirstSplit
    SELECT * FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===','&',NULL)
    
    --Second Split
    SELECT * FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===','&','=')
    

    Scenario Answer:

    SELECT fn.SValue
    FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===', '&', '=')AS fn
    WHERE fn.mid = 2