This is a T-SQL question, I use Microsoft SQL Server 2014. I am joining three tables, which is very straightforward. The tricky part is this: one of the variables, SubtotalKey, takes the form ‘ABD_1999_MAE_1’. I would like to split this variable into its four components, delimited by the underscore, and include the four columns in my output at a specific point in the query. I have a workable solution which uses a scalar function. Workable in the sense that it does what I have just described…but there are performance issues which render it unusable. I’ve since converted the scalar function to a table-valued function, and am using ‘outer apply’ on it as a solution. Unfortunately, this results in 4 rows in the output per result row from the join. Not sure where to go from here - I tried pivot but pivot needs numerical columns to pivot, I think. All help much appreciated.
The table value function in the code below, ufn_SplitString, will split the string above into a table with 1 column and 4 rows. The 4 rows contain the values, respectively, ABD, 1999, MAE, 1.
For the purposes of this question, there are 4 elements in SubtotalKey, but in reality, the number will be variable. Is a solution possible, if I don’t know in advance what the number of required extra columns will be? Here is my code so far:
SELECT
t1.t_proj AS time_period,
ufn.item,
t3.AnnClaimVal AS annuity_outgo_smbel,
t3.DeathClaimVal AS death_outgo_smbel,
t2.SolvSurvXCF AS annuity_outgo_reins,
t2.SolvDeathXCF AS death_outgo_reins,
t2.ReinSwapXCF AS mortswap_fixedleg_payment,
t3.ExpenseValXCF AS ren_exp,
t1.InvExpSCF AS inv_exp,
t1.InvExpReinSCF AS inv_exp_reins
FROM [sch_ImmAnn].[viw_mdlEV_Formulae] t1
INNER JOIN [sch_ImmAnn].[viw_mdl_Formulae] t2
ON t1.t_proj = t2.t_proj AND t1._SubtotalKey = t2._SubtotalKey AND t1._Scenario = t2._Scenario AND t1._ExecRun_UID = t2._ExecRun_UID
INNER JOIN [sch_ImmAnn].[viw_mdlValue_Formulae] t3
ON t1.t_proj = t3.t_proj AND t1._SubtotalKey = t3._SubtotalKey AND t1._Scenario = t3._Scenario AND t1._ExecRun_UID = t3._ExecRun_UID
OUTER APPLY sch_Common.ufn_SplitString(t1._SubtotalKey,'_') ufn
WHERE t1._ExecRun_UID = @ExecUID AND t1._Scenario = @Scenario
AND t1.t_proj >= 0 AND t1.t_proj <= 650
ORDER BY SubtotalKey, time_period
Here is some sample data for t1:
t_proj SubtotalKey Scenario ExecRun_UID InvExpSCF InvExpReinSCF
1 ABD_1999_MAE_1 1 36FA21C8 5334.44 37.88
2 EMM_E12_MAE_3 1 36FA21C8 1894.88 1298.3
3 XYZ_2008_MAE_1 1 36FA21C8 12.99 10009.33
Here is some sample data for t2:
t_proj SubtotalKey Scenario ExecRun_UID SolvSurvXCF SolvDeathXCF ReinSwap
1 ABD_1999_MAE_1 1 36FA21C8 543.88 12.33 1.2
2 EMM_E12_MAE_3 1 36FA21C8 2985.11 59.31 4.6
3 XYZ_2008_MAE_1 1 36FA21C8 309999.12 111.33 9.7
Here is some sample data for t3:
t_proj SubtotalKey Scenario ExecRun_UID ExpenseValXCF AnnClaimVal DeathClaimVal
1 ABD_1999_MAE_1 1 36FA21C8 100 901 678
2 EMM_E12_MAE_3 1 36FA21C8 200 492 121
3 XYZ_2008_MAE_1 1 36FA21C8 554 510 144
Here is the desired output:
t_proj Col1 Col2 Col3 Col4 Scenario ExecRun_UID InvExpSCF InvExpReinSCF SolvSurvXCF SolvDeathXCF ReinSwap ExpenseValXCF AnnClaimVal DeathClaimVal
1 ABD 1999 MAE 1 1 36FA21C8 5334.44 37.88 543.88 12.33 1.2 100 901 678
2 EMM E12 MAE 1 1 36FA21C8 1894.88 1298.3 2985.11 59.31 4.6 200 492 121
3 XYZ 2008 MAE 1 1 36FA21C8 12.99 10009.33 309999.12 111.33 9.7 554 510 144
Function code:
ALTER FUNCTION [sch_Common].[ufn_SplitString]
(
@Input NVARCHAR(MAX),
@Character CHAR(1)
)
RETURNS @Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE @StartIndex INT, @EndIndex INT
SET @StartIndex = 1
IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
BEGIN
SET @Input = @Input + @Character
END
WHILE CHARINDEX(@Character, @Input) > 0
BEGIN
SET @EndIndex = CHARINDEX(@Character, @Input)
INSERT INTO @Output(Item)
SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)
SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
END
RETURN
END