SQL描述(2)

很久之前就想寫出來,就是因爲自己太懶,憋了怎麼久。本文關於使用ORACLE分析函數對一些經濟指標進行計算。表indi_value有3個關鍵的字段:indi_date,indi_value,indi_id分別對應 指標日期,指標值,指標ID。這個表中保存了很多種類的經濟指標,如CPI,RPI,GDP,這些指標通過 指標ID來標識。下面是針對CPI做的處理,公式如下:


公式說明:將2010年1月份當作基期。分別計算基期前後的定基價格指數。直接看代碼

with base as ( select indi_date,indi_value 
               from indi_value 
			   -- 獲取20060101  -  20131101區間內要計算的數據
               where  indi_id='C0A0102' and indi_date between  '20060101'  and  '20131101' 
             ),
   ---獲取大於基期的數據,數據按日期升序,並且使基期=100,往後的值都爲空,然後通過行間計算,進行填補
      up as  (select indi_date,indi_value,
	                 case when indi_date like '201001%' 
	                 then 100 else null end as v,rank() OVER(order by indi_date) as d
              from base
              where indi_date between   '20100101'  and '20131101'),
      upx as (select d,v
              from up  model
              dimension by (d)
              measures (indi_value,v)
              RULES UPDATE
              (
                V[d>1]=v[cv(d)-1]*(1+(indi_value[cv(d)]-100)/100) --大於基期的計算公式
              )
             ),
 --獲取小於基期的數據,結尾日期要能夠將基期數據包含到要計算的數據中,數據按日期倒序,
 --並且使基期=100,往後的值都爲空,然後通過行間計算,進行填補  
       down as (select indi_date,indi_value,
	                   case when indi_date like '201001%' 
					   then 100 else null end as v,rank() OVER(order by indi_date desc) as d
              from base
              where indi_date  between '20060101' and  '20100201'),
       downx as (select d,v
              from down  model
              dimension by (d)
              measures (indi_value,v)
              RULES UPDATE
              (
                V[d>1]=v[cv(d)-1]/(1+(indi_value[cv(d)-1]-100)/100) --小於基期的計算公式
              )
             )                  
     select u.indi_date,null as v,null as r,x.v as b 
	 from upx x join up u on x.d=u.d
     union
     select d.indi_date,null as v,null as r, x.v as b 
	 from downx x join down d on x.d=d.d


以上語句的結果即爲對CPI的定基價格指數計算結果。其中 C0A0102是 CPI在表中的指標ID。語句基本上分位4部分

第一部分:主要是獲取要計算的時間區間內的所有數據,並放到一個名叫base的臨時表中。

with base as ( select indi_date,indi_value 
               from indi_value 
			   -- 獲取20060101  -  20131101區間內要計算的數據
               where  indi_id='C0A0102' and indi_date between  '20060101'  and  '20131101' 
             ),

第二部分:計算大於基期的那部分數據

 ---獲取大於基期的數據,數據按日期升序,並且使基期=100,往後的值都爲空,然後通過行間計算,進行填補
      up as  (select indi_date,indi_value,
	                 case when indi_date like '201001%' 
	                 then 100 else null end as v,rank() OVER(order by indi_date) as d
              from base
              where indi_date between   '20100101'  and '20131101'),
      upx as (select d,v
              from up  model
              dimension by (d)
              measures (indi_value,v)
              RULES UPDATE
              (
                V[d>1]=v[cv(d)-1]*(1+(indi_value[cv(d)]-100)/100) --大於基期的計算公式
              )
             )
第三部分:計算小於基期的那部分數據,原理同第二部分。但要注意是數據日期的倒序。

第四部分:將第二,第三部分的計算結果整合起來

     select u.indi_date,null as v,null as r,x.v as b 
	 from upx x join up u on x.d=u.d
     union
     select d.indi_date,null as v,null as r, x.v as b 
	 from downx x join down d on x.d=d.d

其中第二,第三部分又可以分爲2個步驟。

(1)是還是獲取要計算的數據,並添加一列作爲計算結果,且基期對應的值爲100。添加一列排序號作爲(2)步的取值下標。

(2)使用oracle提供的行間計算函數 model 來根據(1)中的indi_value,和 第一行的基期結果100來計算第二行的定基價格指數。

這樣就會一行一行的計算下去,後一行的結果總是基於前一行的值來計算。(1)中的列 d 可以起類似於數組的作用。

measures 後面的 rules update是可以去掉的。




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