【開發心得】存儲過程實現金融監管報表(含後記)

背景介紹

題外話:疫情過了以後,我們是最早上班的一批人,當時的街上還沒有人,其實反而是安全的,現在街上的人多起來了,更加要注意安全了。作爲IT從業人員,不能長期居家辦公,有點兒遺憾,不過從另外一個角度來說,一個人獨處,總是不如在單位裏有人氣。

本項目主要是爲了應付監管機構對於數據統計的要求而實現的,由於監管對於數據的細節關心不多,主要是將數據用於統計分析。所以日常改動並不多,如果不是這次疫情,估計這個需求也不會提出來,本次是爲了統計貸款用途,估計是希望對於貸款的投放更加精準。

整體思路

好在貸款用途我們一直都在做統計,這次的修改主要是針對數據輸出的改動。
系統也做了前後端的分離,由於並不是對列的新增,所以在前端並不需要修改。
後端比較特殊,這張報表當時過於複雜,結果是用存儲過程實現的,本文的重點就是介紹這個存儲過程的實現。

框架分析

這個代碼主要是每個月執行一次,統計各種分類標準,並且將數據固化下來。舉例來說:
金額分類(大於30萬小於50萬)
期限分類(大於3個月小於6個月)
行業分類(各種行業,你懂得,監管也不一定懂)
每個分類後面就是一些統計值,主要是統計類金額,比如平均數,累計數,日均、月均、年均等等。
所以代碼的大概框架是這樣的

聲明各種變量

如剛纔的各種統計類金額

創建一個臨時表

用Declare Tabel命令,稍後存放中間數據,這個表的字段與數據庫中最終存儲數據的物理表是一致的。

創建分類臨時表

存放各種分類標準,以便稍後與明細數據表進行關聯,並向其中添加數據,例如本次新增的貸款用途,代碼如下:

IF(@StatClass='主體分類')
	BEGIN
		INSERT INTO @ParentTypeTable(ParentType) SELECT '個人類'
		INSERT INTO @ParentTypeTable(ParentType) SELECT '個人涉農類'
		INSERT INTO @ParentTypeTable(ParentType) SELECT '企業類'
		INSERT INTO @ParentTypeTable(ParentType) SELECT '企業涉農類'
	END
IF(@StatClass='貸款用途')
	BEGIN
		INSERT INTO @ParentTypeTable(ParentType,DictionaryCode)
		SELECT DictionaryName,DictionaryCode FROM dbo.SYSDictionary WHERE ParentId=68
	END

代碼可以看出來,一共有兩種方式插入數據,第一種是監管臨時要求的,只能直接出入中文,另一種是系統本身就存在的,可以直接從樣本表裏讀取。

數據特殊處理

對於一些特殊的統計,都放在這裏,以便在最終生成數據之前,全部處理完畢。

循環插入Key數據

根據上面的步驟準備,將明細數據表裏的數據進行分類關聯並插入臨時表,比如類似下面的代碼:

ELSE IF @StatIndex='企業類'	
	INSERT INTO @RepaymentAutoTable( RepaymentAutoId,ContractId )
	SELECT MFRepaymentAuto.Id,MFRepaymentAuto.ContractId FROM dbo.MFRepaymentAuto
	LEFT JOIN dbo.CRMCustomer ON CRMCustomer.Id=MFRepaymentAuto.CustomerId
	WHERE AmountType=5 AND CRMCustomer.CustomerType=0
ELSE IF (@StatClass='貸款用途')
	INSERT INTO @RepaymentAutoTable( RepaymentAutoId,ContractId )
	SELECT MFRepaymentAuto.Id,MFRepaymentAuto.ContractId FROM dbo.MFRepaymentAuto
	LEFT JOIN dbo.MFContract ON MFRepaymentAuto.ContractId=MFContract.Id
	WHERE AmountType=5 AND MFContract.LoanReason=@DictionaryCode

由上述代碼可以看出,在插入明細數據的時候,也分爲了兩種情況,一種是監管與系統不一致分類的情況,只能靠代碼硬處理實現;另外一種,就是可以直接從系統中獲取,從而自動填充數據。

循環插入明細數據

爲了加快效率,此處將最終數據的獲取分爲兩步,剛纔是指插入key,現在就可以把key對應的實際數據都取出來了,這樣做,有兩個好處:
加快表關聯的效率
將統計數據的邏輯與key關聯邏輯分開,便於今後維護
不過此處有個問題,用in來進行了數據匹配,降低了數據的select效率,是將來仍然可以改進的地方,好在每次匹配的分類數據在臨時表裏,一般不會超過10條數據,性能還可以接受。代碼如下:

SELECT @AveMonth=ISNULL(SUM(DATEDIFF(DAY,StartDate,EndDate)*SurplusAmount)/ISNULL(SUM(SurplusAmount),1),0)  
FROM dbo.MFRepaymentAuto 
WHERE CompanyId =@CompanyId AND AmountType=5 AND SurplusAmount>0 AND StatusCode='0'
AND Id IN (SELECT RepaymentAutoId FROM @RepaymentAutoTable) 

無法循環的數據處理

最後一步,就是對於剛纔統計分類裏,不能直接寫入循環的數據處理,例如客戶經理分類的統計,監管機構肯定是不需要的,但是作爲公司內部管理的需求是存在的,爲此,還特意創建了一個客戶經理的臨時表,代碼如下:

DECLARE @strCompany table(CompanyId INT)

小結

隨着年齡增長,之前的很多代碼已經不再存在於記憶中,好在有CSDN可以記憶和分享,希望能給自己有所促進。

後記

今天發現這段代碼的修改還有問題,原來由於分公司的緣故,除了存儲過程,在service端還有一段代碼調用此存儲過程。由於沒有修改這段代碼,結果造成在月底執行彙總的時候,由於分公司沒有數據,結果彙總的虛擬總公司的數據出現了null值,無法插入表,系統報錯。
修改了這段代碼以後,問題解決,爲了將來能夠回溯,將代碼羅列如下:

List<string> strList = new List<string>() { "金額分類", .......,"貸款用途"};
                    foreach (string str in strList)
                    {
                        base.RunProcedure(//後面的代碼省略

究其原因,是因爲當時偷懶,沒有按照實際的場景進行模擬測試造成的,記錄一下,時刻提醒自己做事不能偷懶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章