2017-10-18 109 views
0

這是一個T-SQL問題,我使用的是Microsoft SQL Server 2014.我加入了三個表格,這非常簡單。棘手的部分是這樣的:其中一個變量SubtotalKey採用'ABD_1999_MAE_1'的形式。我想將這個變量分成它的四個組成部分,用下劃線分隔,並在查詢中的特定點處將我的輸出中包含四列。我有一個使用標量函數的可行解決方案。它在我們剛纔所描述的那種意義上是可行的......但是存在導致它無法使用的性能問題。我已經將標量函數轉換爲表值函數,並且使用'outer apply'作爲解決方案。不幸的是,這會在連接的每個結果行的輸出中產生4行。我不知道該從哪裏走 - 我想試過樞軸點,但是樞軸點需要數字柱來樞軸轉動。所有幫助非常感謝。T-SQL - 如何將變量分成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

你必須做一個動態交叉表或動態支點,因爲你沒有列固定數量的每本執行時間。 –

+0

這個問題與其他問題不一樣,因爲我在問是否可以將現有變量拆分爲多個變量。另一個問題沒有解決這個問題。有一種相似之處,我並不知道會有多少列。 – mediaeval

+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 
+0

我可以看到這是如何工作的測試值代替。我怎樣才能將這個工作寫入我現有的代碼中? – mediaeval

+0

Yogesh,我添加了原始問題的示例數據。 – mediaeval

+0

非常感謝。這正是我所期待的。最後一個問題......爲什麼「分裂」在那裏?如果我刪除它,它仍然可以正常工作。雖然微軟的頁面上做了同樣的事情。再次感謝。 – mediaeval