How to separate string based on condition? - sql

COMMSTR1-NAC-NAM-P-C FCPANAM1-NAC-NAM-P-C CHAZEL1-NAT-CBM-P-C
I want to seperate the above string as (Required Output)
col1 col2 col3 col4 col5 col6
COMMSTR1 NAC-NAM-P-C FCPANAM1 NAC-NAM-P-C CHAZEL1 NAT-CBM-P-C
I've tried this.
SELECT Contact_assg_list_src,
Contact_Assg_List_Src =
(
case WHEN Contact_Assg_List_Src IS NOT NULL and Contact_Assg_List_Src <> ''
then left(Contact_Assg_List_Src,patindex('%[-]%',Contact_Assg_List_Src)-1)
ELSE Contact_Assg_List_Src
END),
(case WHEN Contact_Assg_List_Src IS NOT NULL and Contact_Assg_List_Src <> ''
then substring(Contact_Assg_List_Src,(Patindex('%[-]%',Contact_Assg_List_Src + ' ')-1),len(Contact_Assg_List_Src))
ELSE Contact_Assg_List_Src
END)
from dbo.FBMSRAW;
Which gives me output like
col1 col2
COMMSTR1 NAC-NAM-P-C FCPANAM1-NAC-NAM-P-C CHAZEL1-NAT-CBM-P-C
How can I check whether the string has space then separate the string based on that to
get required output?

If you want to do it efficiently in SQL server, I'd advise using a CLR function.
But if you have to do it in T-SQL, this function will achieve it (slowly, and in an increasingly inefficient way)
create function SplitString
(
#splitchar char(1),
#string varchar(500),
#index int
)
returns varchar(500)
as
begin
declare #split int, #start int, #loop bit, #i int, #ret varchar(500)
select #start = 0, #i = 0
select #split = charindex(#splitchar, #string, 0)
if #index>0
select #loop = 1
else
select #loop = 0
while #loop = 1
begin
select #start = #split+1
select #split = charindex(#splitchar, #string, #start+1)
if #split = 0
begin
select #split = len(#string)+1
end
select #i = #i + 1
if #i = #index
begin
select #loop = 0
end
end
if #split>#start
select #ret = substring(#string, #start, #split-#start)
else
select #ret = null
return #ret
end
select dbo.SplitString (' ', 'COMMSTR1-NAC-NAM-P-C FCPANAM1-NAC-NAM-P-C CHAZEL1-NAT-CBM-P-C', [0 based column number])

I have wrote the following script to suit your needs, but your self you need to add some more logic, understand the following script
Create a dummy table
CREATE TABLE TBL_TEMPSTRINGS(STRCOL VARCHAR(200),COL1 VARCHAR(50),
COL2 VARCHAR(50),COL3 VARCHAR(50))
Insert values from your table
INSERT INTO TBL_TEMPSTRINGS
SELECT Contact_assg_list_src From dbo.FBMSRAW
Create a stored procedure to update your dummy table columns, it takes your table name in a string(why you can replace your dummy table with temp table name if you have used)
CREATE PROC SP_SPLITWRODS(#TABLENAME VARCHAR(50),#COLCOUNT INT)
AS
BEGIN
DECLARE #QRY VARCHAR(500)
CREATE TABLE #TBL_TEMP(STRCOL VARCHAR(200))
DECLARE #STRCOL VARCHAR(200)
DECLARE #CURRINDEX INT
DECLARE #TEMP INT
DECLARE #COLINDEX INT
DECLARE #ROWID INT
DECLARE #STRLEN INT
DECLARE #TEMPVALUE VARCHAR(50)
DECLARE #LASTWORD BIT
--CURSOR FOR YOUR TEMP TABLE
DECLARE CUR_TEMP CURSOR LOCAL FOR SELECT STRCOL FROM #TBL_TEMP
--CONSTRUCT QRY FOR FILLING YOUR TABLE
SET #QRY='INSERT INTO #TBL_TEMP SELECT STRCOL FROM ' + #TABLENAME
--FILL TABLE
EXECUTE(#QRY)
OPEN CUR_TEMP
FETCH CUR_TEMP INTO #STRCOL
WHILE ##FETCH_STATUS = 0
BEGIN
SET #CURRINDEX=1
SET #COLINDEX=1
SET #LASTWORD=0
--GET ' ' INDEX
SET #TEMP=CHARINDEX(' ',#STRCOL,#CURRINDEX)
WHILE #TEMP > 0
BEGIN
--YOU WILL GET THE VALUE SEPERATED BY SPACE
SET #TEMPVALUE=SUBSTRING(#STRCOL,#CURRINDEX,#TEMP-#CURRINDEX)
--ADD MORE LOGIC TO UPDATE YOUR COLUMNS (YOUR EXTRA COLUMNS)
--CONTRUCT QRY TO UPDATE CORRESPONDING COL IN YOUR TABLE FOR THE ROW FETCHED
--THIS UPDATES ALL ROWS, YOU NEED TO ADD ONE WHERE CONDITION TO UPDATE THE ROW
SET #QRY='UPDATE ' + #TABLENAME + ' SET COL' + CAST(#COLINDEX AS VARCHAR) + '=''' + #TEMPVALUE + ''''
EXEC(#QRY)
--INCREMENT COL INDEX AFTER UPDATE OF LAST COLUMN
SET #COLINDEX=#COLINDEX+1
SET #CURRINDEX=#TEMP+1
SET #TEMP=CHARINDEX(' ',#STRCOL,#CURRINDEX)
IF #TEMP=0 AND #LASTWORD=0
BEGIN
SET #TEMP=LEN(#STRCOL)+1
SET #LASTWORD=1
END
END
FETCH CUR_TEMP INTO #STRCOL
END
CLOSE CUR_TEMP
DEALLOCATE CUR_TEMP
END
Execute your proc
EXEC SP_SPLITWRODS 'TBL_TEMPSTRINGS',1
See your updated dummy table
SELECT * FROM TBL_TEMPSTRINGS
Presently it is updates 3 columns split by the space, you need to add your own logic to update the columns based on the string you have received(seperated by space).
Hope it helps

First a function to split the text
create function [dbo].[f_split]
(
#param nvarchar(max),
#delimiter char(1)
)
returns #t table (val nvarchar(max), seq int)
as
begin
set #param += #delimiter
;with a as
(
select cast(1 as bigint) f, charindex(#delimiter, #param) t, 1 seq
union all
select t + 1, charindex(#delimiter, #param, t + 1), seq + 1
from a
where charindex(#delimiter, #param, t + 1) > 0
)
insert #t
select substring(#param, f, t - f), seq from a
option (maxrecursion 0)
return
end
go
Query to display the result, assuming there are max 6 'words'
declare #t table(txt nvarchar(500))
insert #t values ('COMMSTR1-NAC-NAM-P-C FCPANAM1-NAC-NAM-P-C CHAZEL1-NAT-CBM-P-C'),
('t1 t2 t3 t4 t5 t6')
select * from #t t
outer apply
(
select max(case when seq = 1 then val end) col1,
max(case when seq = 2 then val end) col2,
max(case when seq = 3 then val end) col3,
max(case when seq = 4 then val end) col4,
max(case when seq = 5 then val end) col5,
max(case when seq = 6 then val end) col6
from dbo.f_split(t.txt, ' ')
) b

Related

Append comma delimited string with other data to another table

I am running SQL Server 2008. in a stored procedure, I need to copy TableA to TableB by making a comma-delimted string from a subset of columns in TableA and write it along with some other data to TableB.
TableA contains 12 text columns named 'Column1' thru 'Column12'.
For each row in TableA I need a comma-separated string built from a variable range of columns defined by parameters #startCol and #endCol passed to the stored procedure. I need to copy #startCol and #endCol plus the string to another table.
TableB:
StartCol, EndCol, CommaDelim
This is what I'm trying:
INSERT INTO TableB SELECT #startCol as StartCol, #endCol As EndCol,
COALESCE(???) as CommaDelim
I can't figure out what to pass to the COALESCE function. I'm not even sure I should be using COALESCE. I'm not averse to dynamic SQL
TableA:
Column1 Column2 Column3 ….
'A1' 'A2' 'A3'
'B1' 'B2' 'B3'
.
.
.
what I want in TableB is
StartCol EndCol CommaDelim
1 3 'A1,A2,A3'
1 3 'B1,B2,B3'
one record for each record in TableA
I can't get any result set - I keep getting syntax errors in the COALESCE part
Perhaps a little over-developed, but here is a technique that does NOT require dynamic SQL
Notice I set Columns between 1 & 2, but you can set any range
Example
Declare #YourTable Table ([Column1] varchar(50),[Column2] varchar(50),[Column3] varchar(50))
Insert Into #YourTable Values
('A1','A2','A3')
,('B1','B2','B3')
Declare #Col1 int = 1
Declare #Col2 int = 2
Select StartCol = #Col1
,EndCol = #Col2
,C.*
From #YourTable A
Cross Apply ( values (cast((Select A.* for XML RAW,ELEMENTS XSINIL) as xml))) B(XMLData)
Cross Apply ( values (stuff((Select ',' + Value
From (
Select Seq = row_number() over (order by (select null))
,Item = a.value('local-name(.)','varchar(100)')
,Value = a.value('.','varchar(max)')
From B.XMLData.nodes('/row') as C1(n)
Cross Apply C1.n.nodes('./*') as C2(a)
) B1
Where Seq between #Col1 and #Col2
Order By Seq
For XML Path (''))
,1,1,'')
)
) C(CommaDelim)
Returns
StartCol EndCol CommaDelim
1 2 A1,A2
1 2 B1,B2
You will have to convert them into VARCHAR datatype so that you can concatenate them. COALESCE is picking the first null column in the list.
Example:
ISNULL(CONVERT(VARCHAR(Length),Column1),'')+','+ISNULL(CONVERT(VARCHAR(Length),Column2),'')+','+ISNULL(CONVERT(VARCHAR(Length),Column3),'')
Hope that helps!
I came up with a way so that you do not have to create dynamic sql by creating a function. You may have to modify the select statements to match your schema. You can use the function this way:
select dbo.getString(#startCol, #endCol)
create function getString(#startCol int, #endCol int)
returns varchar(40)
as
begin
declare #str varchar(40) = ""
declare #i int = #startCol
if #endCol < #startCol
begin
return #str
end
while #i < #endCol + 1
begin
if #i = 1
begin
select #str = #str + Column1 + ","
from TableA
end
if #i = 2
begin
select #str = #str + Column2 + ","
from TableA
end
if #i = 3
begin
select #str = #str + Column3 + ","
from TableA
end
if #i = 4
begin
select #str = #str + Column4 + ","
from TableA
end
if #i = 5
begin
select #str = #str + Column5 + ","
from TableA
end
if #i = 6
begin
select #str = #str + Column6 + ","
from TableA
end
if #i = 7
begin
select #str = #str + Column7 + ","
from TableA
end
if #i = 8
begin
select #str = #str + Column8 + ","
from TableA
end
if #i = 9
begin
select #str = #str + Column9 + ","
from TableA
end
if #i = 10
begin
select #str = #str + Column10 + ","
from TableA
end
if #i = 11
begin
select #str = #str + Column11 + ","
from TableA
end
if #i = 12
begin
select #str = #str + Column12 + ","
from TableA
end
set #i = #i + 1
end
set #str = substring(#str, 1, len(#str) - 1)
return #str
end

Comma Separated List from SQL Grouping

I'm trying to build comma separated list per group in sql,
As am using Parallel Data Warehouse i need to do this without using FOR XML or recursive function ( not supported ).
any other way to achieve this ?
Input:
ID Value
1 2
1 3
1 4
2 1
2 10
Output:
ID List
1 2,3,4
2 1,10
This will not perform well at all so I recommend you use some other solution (like a SQL Server linked server to PDW) if you need performance. But I believe this should work on PDW:
declare #ID int = (select min(ID) from tbl);
declare #Value int = -1;
declare #concat varchar(8000) = '';
create table #tmp (
ID int,
[concat] varchar(8000)
)
with (distribution=hash(ID), location=user_db);
while #ID is not null
begin
set #Value = (select min([Value]) from tbl where ID = #ID and [Value]>#Value);
if #Value is not null
set #concat = #concat + case when #concat = '' then '' else ',' end + cast(#Value as varchar(8000));
else
begin
insert #tmp (ID, [concat])
values (#ID, #concat);
set #ID = (select min(ID) from tbl where ID > #ID);
set #Value = -1;
set #concat = '';
end
end
select * from #tmp;
drop table #tmp;

Sql Query To Find Relevant Match

I am trying to write a query that should return the following output:
val1 = 'GREAT'
val2 = 'TAGER'
See above have the same characters and it should return 'Exist' if the match is found. Otherwise, if there is a character missing, then 'Not exist'. I am using CASE to get the required output and was wondering if it could be done using SUBSTRING, CHARINDEX etc. Hoping to get a solution or idea to do so. Thanks.
You can make it as a function / procedure according to your needs.
DECLARE #S1 VARCHAR(100)
DECLARE #S2 VARCHAR(100)
SELECT #S1 = val1
,#S2 = val2
FROM <TABLE_NAME>
DECLARE #c CHAR(1)
DECLARE #i TINYINT
DECLARE #o1 VARCHAR(100) = ''
DECLARE #o2 VARCHAR(100) = ''
WHILE DataLength(#s1) > 0
BEGIN
SET #c = Left(#s1, 1)
SET #s1 = Substring(#s1, 2, len(#s1))
SET #i = 1
WHILE #i <= Len(#o1)
AND #c > substring(#o1, #i, 1)
SET #i += 1
SET #o1 = left(#o1, #i - 1) + #c + substring(#o1, #i, len(#o1))
END
WHILE DataLength(#s2) > 0
BEGIN
SET #c = Left(#s2, 1)
SET #s2 = Substring(#s2, 2, len(#s2))
SET #i = 1
WHILE #i <= Len(#o2)
AND #c > substring(#o2, #i, 1)
SET #i += 1
SET #o2 = left(#o2, #i - 1) + #c + substring(#o2, #i, len(#o2))
END
SELECT CASE
WHEN #o1 = #o2
THEN 'Exist'
ELSE 'Not Exist'
END
This is a custom script for you
Run this SP first
IF(OBJECT_ID('CharSplit')) IS NOT NULL
DROP PROCEDURE CharSplit;
GO
CREATE PROC CharSplit
#Words VARCHAR(MAX)
AS
BEGIN
IF OBJECT_ID('tempdb..#temp1') IS NOT NULL
DROP TABLE #temp1;
CREATE TABLE #temp1
(
letter CHAR(1), freq INT
);
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL
DROP TABLE #temp2;
CREATE TABLE #temp2
(
letter CHAR(1), freq INT
);
DECLARE #t VARCHAR(MAX);
DECLARE #I INT;
--SET #Words = 'sanuantony';
SELECT #I = 0;
WHILE(#I < LEN(#Words) + 1)
BEGIN
SELECT #t = SUBSTRING(#words, #I, 1);
INSERT INTO #temp1
(letter, freq
)
VALUES
(#t, 0
);
SET #I = #I + 1;
END;
TRUNCATE TABLE #temp2;
INSERT INTO #temp2
(letter, freq
)
SELECT letter, COUNT(freq)
FROM #temp1
GROUP BY letter;
SELECT *
FROM #temp2
ORDER BY letter;
END;
Now Just try your business logic
DECLARE #t1 AS TABLE
(
letter CHAR(1), freq INT
);
DECLARE #t2 AS TABLE
(
letter CHAR(1), freq INT
);
INSERT INTO #t1
EXEC charSplit 'alammalay';
INSERT INTO #t2
EXEC charSplit 'malayalam';
IF(
(
SELECT COUNT(1)
FROM #t1
) =
(
SELECT COUNT(1)
FROM #t2
)
AND
(
SELECT COUNT(1)
FROM #t2
) =
(
(
SELECT COUNT(1)
FROM #t1
)
UNION
(
SELECT COUNT(1)
FROM #t2
)
)
)
SELECT 'Both are matching' AS result;
ELSE
SELECT 'Both are not matching' AS result;

Retrieve multiple pieces of data from a single SQL Server variable

I have two variables like:
#FieldName
#values
Those two variables hold values like:
#FieldName - contains [a],[b],[c],[d]
#values - contains 5,6,7,8
Now I need to retrieve the data of column 'b' & 'd' only.
How can we get b=6 & d=8?
Thanks in advance.
well I hate to do such a things on SQL Server, but
declare #FieldName nvarchar(max) = '[a],[b],[c],[d]'
declare #values nvarchar(max) = '5,6,7,8'
declare #i int, #j int, #break int
declare #a nvarchar(max), #b nvarchar(max), #result nvarchar(max)
select #break = 0
while #break = 0
begin
select #i = charindex(',', #FieldName), #j = charindex(',', #values)
if #i > 0 and #j > 0
begin
select #a = left(#FieldName, #i - 1), #b = left(#values, #j - 1)
select #FieldName = right(#FieldName, len(#FieldName) - #i), #values = right(#values, len(#values) - #j)
end
else
begin
select #a = #FieldName, #b = #values, #break = 1
end
if #a in ('[b]', '[d]')
select #result = isnull(#result + ' & ', '') + #a + '=' + #b
end
select #result
You can also put all this list into temporary/variable table and do join.
select *
from
(
select T.<yourcolumn>, row_number() over (order by T.<yourcolumn>) as rownum
from <temptable1> as T
) as F
inner join
(
select T.<yourcolumn>, row_number() over (order by T.<yourcolumn>) as rownum
from <temptable2> as T
) as V on V.rownum = F.rownum
Or, even better, you can pass parameters into sp in xml form and not in distinct lists
Try this :
Using XML i'm are trying to spilt the values and storing the result in a table variable
DECLARE #FieldName VARCHAR(MAX),
#values varchar(max)
SET #FieldName = 'a,b,c,d';
SET #values = '5,6,7,8'
SET #FieldName = #FieldName + ',';
SET #values = #values + ',';
DECLARE #X XML
SET #X = CAST('<Item>' + REPLACE(#FieldName, ',', '</Item><Item>') + '</Item>' AS XML)
Declare #X1 XML
Set #X1=CAST('<Position>' + REPLACE(#values, ',', '</Position><Position>') + '</Position>' AS XML)
Declare #FieldSample table
(
FieldName char(1),
rowNum int
)
Declare #valueSample table
(position int,
rowNum int)
Insert into #FieldSample(rowNum,FieldName)
Select * from (
SELECT row_number() over (order by (select 0)) as rowNum, t.value('.', 'char(1)') as field
FROM #x.nodes('/Item') as x(t)
) as a
where a.field !=''
Insert into #valueSample(rowNum,position)
Select * from (
Select row_number() over (order by (select 0)) as rowNum, k.value('.', 'int') as position
from #X1.nodes('/Position') as x1(k)
) as b
where b.position !=0
Basically the last logic you can change it based on how you intend to get the data
Select a.FieldName,b.position from #FieldSample as a
inner join #valueSample as b
on a.rowNum=b.rowNum
where b.position = 6 or b.position =8

How to change case in string

My table has one column that contain strings like: ” HRM_APPLICATION_DELAY_IN”
I want to perform bellow operations on each row on this column
convert to lower case
remove underscore “_”
change case (convert to upper case) of the character after the underscore like: ” hrm_Application_Delay_In”
Need help for conversion. Thanks for advance
Here is a function to achieve it:
create function f_test
(
#a varchar(max)
)
returns varchar(max)
as
begin
set #a = lower(#a)
while #a LIKE '%\_%' ESCAPE '\'
begin
select #a = stuff(#a, v, 2, upper(substring(#a, v+1,1)))
from (select charindex('_', #a) v) a
end
return #a
end
Example:
select dbo.f_test( HRM_APPLICATION_DELAY_IN')
Result:
hrmApplicationDelayIn
To update your table here is an example how to write the syntax with the function:
UPDATE <yourtable>
SET <yourcolumn> = dbo.f_test(col)
WHERE <yourcolumn> LIKE '%\_%' ESCAPE '\'
For a variable this is overkill, but I'm using this to demonstrate a pattern
declare #str varchar(100) = 'HRM_APPLICATION_DELAY_IN';
;with c(one,last,rest) as (
select cast(lower(left(#str,1)) as varchar(max)),
left(#str,1), stuff(lower(#str),1,1,'')
union all
select one+case when last='_'
then upper(left(rest,1))
else left(rest,1) end,
left(rest,1), stuff(rest,1,1,'')
from c
where rest > ''
)
select max(one)
from c;
That can be extended to a column in a table
-- Sample table
declare #tbl table (
id int identity not null primary key clustered,
str varchar(100)
);
insert #tbl values
('HRM_APPLICATION_DELAY_IN'),
('HRM_APPLICATION_DELAY_OUT'),
('_HRM_APPLICATION_DELAY_OUT'),
(''),
(null),
('abc<de_fg>hi');
-- the query
;with c(id,one,last,rest) as (
select id,cast(lower(left(str,1)) as varchar(max)),
left(str,1), stuff(lower(str),1,1,'')
from #tbl
union all
select id,one+case when last='_'
then upper(left(rest,1))
else left(rest,1) end,
left(rest,1), stuff(rest,1,1,'')
from c
where rest > ''
)
select id,max(one)
from c
group by id
option (maxrecursion 0);
-- result
ID COLUMN_1
1 hrm_Application_Delay_In
2 hrm_Application_Delay_Out
3 _Hrm_Application_Delay_Out
4
5 (null)
6 abc<de_Fg>hi
select
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(lower('HRM_APPLICATION_DELAY_IN'),'_a','A'),'_b','B'),'_c','C'),'_d','D'),'_e','E'),'_f','F'),
'_g','G'),'_h','H'),'_i','I'),'_j','J'),'_k','K'),'_l','L'),
'_m','M'),'_n','N'),'_o','O'),'_p','P'),'_q','Q'),'_r','R'),
'_s','S'),'_t','T'),'_u','U'),'_v','V'),'_w','W'),'_x','X'),
'_y','Y'),'_z','Z'),'_','')
Bellow two steps can solve problem,as example i use sys.table.user can use any one
declare #Ret varchar(8000), #RetVal varchar(8000), #i int, #count int = 1;
declare #c varchar(10), #Text varchar(8000), #PrevCase varchar, #ModPrefix varchar(10);
DECLARE #FileDataTable TABLE(TableName varchar(200))
INSERT INTO #FileDataTable
select name FROM sys.tables where object_name(object_id) not like 'sys%' order by name
SET #ModPrefix = 'Pur'
DECLARE crsTablesTruncIns CURSOR
FOR select TableName FROM #FileDataTable
OPEN crsTablesTruncIns
FETCH NEXT FROM crsTablesTruncIns INTO #Text
WHILE ##FETCH_STATUS = 0
BEGIN
SET #RetVal = '';
select #i=1, #Ret = '';
while (#i <= len(#Text))
begin
SET #c = substring(#Text,#i,1)
--SET #Ret = #Ret + case when #Reset=1 then UPPER(#c) else LOWER(#c)
IF(#PrevCase = '_' OR #i = 1)
SET #Ret = UPPER(#c)
ELSE
SET #Ret = LOWER(#c)
--#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
if(#c like '[a-zA-Z]')
SET #RetVal = #RetVal + #Ret
if(#c = '_')
SET #PrevCase = '_'
else
SET #PrevCase = ''
SET #i = #i +1
end
SET #RetVal = #ModPrefix + #RetVal
print cast(#count as varchar) + ' ' + #RetVal
SET #count = #count + 1
EXEC sp_RENAME #Text , #RetVal
SET #RetVal = ''
FETCH NEXT FROM crsTablesTruncIns INTO #Text
END
CLOSE crsTablesTruncIns
DEALLOCATE crsTablesTruncIns
I'd like to show you my nice and simple solution. It uses Tally function to split the string by pattern, in our case by underscope. For understanding Tally functions, read this article.
So, this is how my tally function looks like:
CREATE FUNCTION [dbo].[tvf_xt_tally_split](
#String NVARCHAR(max)
,#Delim CHAR(1))
RETURNS TABLE
as
return
(
WITH Tally AS (SELECT top (select isnull(LEN(#String),100)) n = ROW_NUMBER() OVER(ORDER BY [name]) from master.dbo.syscolumns)
(
SELECT LTRIM(RTRIM(SUBSTRING(#Delim + #String + #Delim,N+1,CHARINDEX(#Delim,#Delim + #String + #Delim,N+1)-N-1))) Value, N as Ix
FROM Tally
WHERE N < LEN(#Delim + #String + #Delim)
AND SUBSTRING(#Delim + #String + #Delim,N,1) = #Delim
)
)
This function returns a table, where each row represents part of string between #Delim (in our case between underscopes). Rest of the work is simple, just cobination of LEFT, RIGHT, LEN, UPPER and LOWER functions.
declare #string varchar(max)
set #string = ' HRM_APPLICATION_DELAY_IN'
-- convert to lower case
set #string = LOWER(#string)
declare #output varchar(max)
-- build string
select #output = coalesce(#output + '_','') +
UPPER(left(Value,1)) + RIGHT(Value, LEN(Value) - 1)
from dbo.tvf_xt_tally_split(#string, '_')
-- lower first char
select left(lower(#output),1) + RIGHT(#output, LEN(#output) - 1)