Search code examples
sqlsql-serversql-function

How to achieve the following using functions/stored procedure in SQL Server database


I have the following table with following data as

                                            Tab1
FutureMISBoundaryVersion  CurrentMISBoundaryVersion  FutureHAMBoundaryVersion  CurrentHAMBoundaryVersion 
2:21,5:50,4:55,7:80,9:33  2:12,5:40,4:35,7:60,9:87   2:52,5:90,4:75,7:30,9:57  2:42,5:60,4:95,7:70,9:37   

This key value pair has to be split into and the value of each key has to be inserted into another table in the following fashion

FutureMIS-OAKVersion |FutureMIS-HAMVersion |FutureMIS-DURVersion | FutureMIS-BURVersion| FutureMIS-YRTVersion |DeviceMIS-OAKVersion|DeviceMIS-HAMVersion |DeviceMIS-DURVersion| DeviceMIS-BURVersion| DeviceMIS-YRTVersion
              33     |              80     |            21       |            55       |  50                  | 87                 |  60                 |12                  |35                   | 40

i,e: when it finds column 'FutureMISBoundaryVersion' in tab1 then its value '2:21,5:50,4:55,7:80,9:33' will be split and its value is inserted in such a way that the corresponding value of key 2 i,e:21 will be inserted into FutureMIS-DURVersion column.

Similarly key 5's value 50 will be inserted into FutureMIS-BURVersion column and so on for other keys

when it finds column 'CurrentMISBoundaryVersion' then
'2:12,5:40,4:35,7:60,9:87' will be split and its value is inserted in such a way that the corresponding value of key 2 i,e:12 will be inserted into CurrentMIS-DURVersion column similarly key 5's 40 value will be inserted into DeviceMIS-YRTVersion column and so on for other columns of the source table.

The table structure may extend as I have shown only 4 source table column but logic for all the columns remain same


Solution

  • Very funky requirements to be honest. Please note solution below will work only in SQL Server 2016+ as I'm using JSON to parse the data. However you can write your own parser, in this case code will work in almost all versions of SQL Server.

    Parse function:

    CREATE FUNCTION dbo.ParseIt(@Type NVARCHAR(255),@Value NVARCHAR(MAX))
    RETURNS @Parsed TABLE (Code NVARCHAR(255),Value NVARCHAR(255))
    AS
    BEGIN
        INSERT INTO @Parsed(Code,Value)
        SELECT @Type + '-' + m.Code + 'Version' AS [Code],p.[1] AS [Value]
        FROM (
            SELECT j.[key] AS [ID],i.[key],i.value
            FROM OPENJSON('["' + REPLACE(@Value,',','","') + '"]') j
            CROSS APPLY OPENJSON('[' + REPLACE(j.[value],':',',') + ']') i
        ) a
        PIVOT(MAX(a.value) FOR a.[key] IN ([0],[1])) p
        INNER JOIN ( VALUES
            (2,'DUR')
            ,(4,'BUR')
            ,(5,'YRT')
            ,(7,'HAM')
            ,(9,'OAK')
        ) m(ID, Code) ON m.ID = p.[0]
        ;
        RETURN;
    END
    

    Initial data:

    DECLARE @Table TABLE (FutureMISBoundaryVersion NVARCHAR(MAX), CurrentMISBoundaryVersion NVARCHAR(MAX),FutureHAMBoundaryVersion NVARCHAR(MAX),CurrentHAMBoundaryVersion NVARCHAR(MAX));
    INSERT INTO @Table(FutureMISBoundaryVersion,CurrentMISBoundaryVersion,FutureHAMBoundaryVersion,CurrentHAMBoundaryVersion)VALUES
        ('2:21,5:50,4:55,7:80,9:33','2:12,5:40,4:35,7:60,9:87','2:52,5:90,4:75,7:30,9:57','2:42,5:60,4:95,7:70,9:37')
    ;
    

    The code:

    SELECT COALESCE(p.[FutureMIS-OAKVersion],'') AS [FutureMIS-OAKVersion]
        ,COALESCE(p.[FutureMIS-HAMVersion],'') AS [FutureMIS-HAMVersion]
        ,COALESCE(p.[FutureMIS-DURVersion],'') AS [FutureMIS-DURVersion]
        ,COALESCE(p.[FutureMIS-BURVersion],'') AS [FutureMIS-BURVersion]
        ,COALESCE(p.[FutureMIS-YRTVersion],'') AS [FutureMIS-YRTVersion]
        ,COALESCE(p.[DeviceMIS-OAKVersion],'') AS [DeviceMIS-OAKVersion]
        ,COALESCE(p.[DeviceMIS-HAMVersion],'') AS [DeviceMIS-HAMVersion]
        ,COALESCE(p.[DeviceMIS-DURVersion],'') AS [DeviceMIS-DURVersion]
        ,COALESCE(p.[DeviceMIS-BURVersion],'') AS [DeviceMIS-BURVersion]
        ,COALESCE(p.[DeviceMIS-YRTVersion],'') AS [DeviceMIS-YRTVersion]
    FROM (
        SELECT f.Code,f.Value FROM @Table t CROSS APPLY dbo.ParseIt('FutureMIS',t.FutureMISBoundaryVersion) f
        UNION ALL 
        SELECT f.Code,f.Value FROM @Table t CROSS APPLY dbo.ParseIt('DeviceMIS',t.CurrentMISBoundaryVersion) f
    ) a
    PIVOT(MAX(a.Value) FOR a.Code IN ([DeviceMIS-BURVersion],[DeviceMIS-DURVersion],[DeviceMIS-HAMVersion],[DeviceMIS-OAKVersion]
        ,[DeviceMIS-YRTVersion],[FutureMIS-BURVersion],[FutureMIS-DURVersion],[FutureMIS-HAMVersion],[FutureMIS-OAKVersion]
        ,[FutureMIS-YRTVersion])) p
    ;