这是一个T-SQL问题,我使用Microsoft SQL Server 2014.我正在加入三个表,这非常简单。棘手的部分是:其中一个变量SubtotalKey采用“ABD_1999_MAE_1”形式。我想将此变量拆分为四个组件,由下划线分隔,并在查询中的特定点包含输出中的四列。我有一个可行的解决方案,它使用标量函数。在它完成我刚才描述的意义上是可行的......但是存在使其无法使用的性能问题。我已经将标量函数转换为表值函数,并在其上使用“外部应用”作为解决方案。不幸的是,这会导致连接中每个结果行的输出中有4行。不知道从哪里开始 - 我试过枢轴,但枢轴需要数字列来转动,我想。所有人都非常感谢。
下面代码中的表值函数ufn_SplitString将上面的字符串拆分为一个包含1列和4行的表。 4行分别包含ABD,1999,MAE,1的值。
出于这个问题的目的,SubtotalKey中有4个元素,但实际上,这个数字是可变的。如果我事先不知道所需的额外列数是多少,那么解决方案是否可行? 到目前为止,这是我的代码:
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
以下是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
以下是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
以下是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
这是所需的输出:
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
功能代码:
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
答案 0 :(得分:1)
假设你看下面的内容(Varibale:ABD_1999_MAE_1
):
Column1 Column2 Column3 Column4
ABD 1999 MAE 1
如果,以上是正确的,那么您可以使用XML
方法和CROSS APPLY
SELECT DISTINCT
A.t_proj,
split.a.value('/X[1]', 'NVARCHAR(MAX)') Col1,
split.a.value('/X[2]', 'NVARCHAR(MAX)') Col2,
split.a.value('/X[3]', 'NVARCHAR(MAX)') Col3,
split.a.value('/X[4]', 'NVARCHAR(MAX)') Col4,
A.Scenario,
A.ExecRun_UID,
A.InvExpSCF,
A.InvExpReinSCF,
A.SolvSurvXCF,
A.SolvDeathXCF,
A.ReinSwap,
A.ExpenseValXCF,
A.AnnClaimVal,
A.DeathClaimVal
FROM
(
SELECT T1.t_proj,
CAST('<X>'+REPLACE(T1.SubtotalKey, '_', '</X><X>')+'</X>' AS XML) AS String,
T1.Scenario,
T1.ExecRun_UID,
T1.InvExpSCF,
T1.InvExpReinSCF,
T2.SolvSurvXCF,
T2.SolvDeathXCF,
T2.ReinSwap,
T3.ExpenseValXCF,
T3.AnnClaimVal,
T3.DeathClaimVal
FROM T1
INNER JOIN T2 ON T2.t_proj = T1.t_proj
AND T2.SubtotalKey = T1.SubtotalKey
AND T2.Scenario = T1.Scenario
INNER JOIN T3 ON T3.t_proj = T1.t_proj
AND T3.SubtotalKey = T3.SubtotalKey
AND T3.Scenario = T1.Scenario
) AS A
CROSS APPLY String.nodes('/X') split(a);
期望的结果:
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 3 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