WFU

2016年4月9日 星期六

如何知道病人死亡(Part 2) - ID檔3億筆資料奮戰紀錄

作者: 陳建翰 醫師

前一版文章請看這邊:如何知道病人死亡



在拿到壓死線的新年禮物之後,想說重新再把自己的ID檔資料更新一下。於是,試用了前一版文章所使用的暴力方法:把所有的ID匯入一個大檔當中,找出最後一次入保與最後一次退出保險的日子,去做比較即可。

不過,一旦有心想要把所有的東西一次做完,就會出現很恐怖的事情:

一整天跑不出一張表


對,我花了將近半天的時間把所有的ID檔INSERT到一個檔裡面去,然後跑Max, 就是一整天跑不完。

也就是因為這樣,我就一頭又栽進去ID檔裡面了,花了兩個禮拜的時間繞阿繞繞阿繞,總算給我繞出個頭來!

雖然再下來需要處理一年2800+萬的 ID檔的人應該會越來越少 (國衛院關掉了),我想還是留個紀錄,讓手上跟我一樣有DD與ID的"自營商"們少走一點冤枉路!

先講方法:


1. 把所有的退保都先拉出來 ( 2009以後 TX_CODE = 08, 2009以前 ID_OUT_Status = 1)

2. 把所有的加保都先拉出來 ( 2009以後 TX_CODE = 01, 2009以前 ID_IN_Status = 1)

3. 你已經跑完的原始資料母檔的所有ID拉出來到另外一張表 (Ex: ID_0)

4. 從2013年的退保資料開始比較,建立一張新表( ex. ID_2013_OUT) 用Left outer joint 的方式,把ID_OUT_DATE加到剛剛建立的ID表(ID_0)當中!並且建立 ID 以及 ID_OUT_DATE的 INDEX

注意:要把ID_IN_DATE一起加到裡面去!!後面會用到!!

5. 建立一張表 (ex. ID_OUT),把上一張表( ex. ID_2013_OUT)中有資料的( Where ID_OUT_Date is not null ) 放進去,

6. 再建立另一張表 (ex. ID_Residual),把上一張表( ex. ID_2013_OUT)中沒資料的( Where ID_OUT_Date is null ) 放進去

7. 用沒資料的那一張表 (ex. ID_Residual),建立一張新表( ex. ID_2012_OUT)重複4,再去比較2012年的退保資料

8. 把上一張表( ex.  ID_2012_OUT)中有資料的( Where ID_OUT_Date is not null ) 放進去步驟6中建立的那張表 (ex. ID_OUT)去,然後,把沒資料的放到另一張表 (ex. ID_Residual)。可以用同一個名字,但記得在Create之前一定要把上一張表 Drop掉!!

9. 重複7 和 8,直到比完ID2002為止!

10. 建立另一張表(ex. ID_OUT_01)把有所有ID及ID_OUT_Date 那張表 (ex. ID_OUT),取 Max (ID_OUT_Date),就有這些 ID 的最後一筆退保日期!!

11. 用剛剛建立那張表(ex. ID_OUT_01), 同樣的方法,重複4-10,把MAXINDATE也給抓進去(假設最後的表是ID_IN_01)

12. 用Left outer joint, Combine ID_OUT_01跟 ID_IN_01,並且建立 ID 以及 MAXOUTDATE的 INDEX (ex. 20_ID0 )

13. 建立一張表(ex: 20_ID1),Left outer joint, 把上一張表(20_ID0)跟 之前做的退保表的所有資料  (ex. ID_OUT) 做Combine!! 

14. 比較表中(ex: 20_ID1)的 MAXINDATE 以及剛剛joint進來的ID_IN_Date (ex. ID_OUT), 看哪個比較大!!用大的作正式的MaxINDATE!!

15. 就可以做比較了!! (詳見前一版文章:如何知道病人死亡)

討論:


1. ID檔是會重複堆疊的(如下圖),但不是每一個ID檔都有重複堆疊的情況。


如果所有的資料檔都存留在ID檔當中,那理論上,以前的資料都不應該變。

比如說:在ID2012內,2009-2011退保的人,跟ID2013內, 2009-2011退保的人應該一樣多!

不過,並不是這樣!

實際運算起來,ID2012內2009-2011的退保人數是483067人,但在ID2013內,卻只有455570人。同樣的狀況發生在其他各年度的區間也都有類似的情形。

這說明,ID檔內的退保紀錄是會堆疊,但不是每一筆都會!!

我不知道健保到底如何登錄這些資料,我猜這可能跟依附就保有關係。老爸死了,但老爸生前是依附我就保,所以只要我的工作換了一異動,所有我的眷屬資料可能就一起都異動了,因次會不斷地被累積再各個ID檔當中。

所以,還是得老老實實的把每個年度的ID檔通通拿出來比較,才能夠得到確切的數字!

2. 要跟將近3億筆的資料硬拚也不是沒問題,不過我的經驗是不好的!畢竟我們的電腦不是ALPHAGO,於是我們只能切他電路繞路。

死亡只有一個情況,就是退保!所以要知道死亡,只有退保是需要關注的

很好,這樣筆數一年就下探到250(ID2002)-450萬(ID2013)筆左右,總數一下子就只剩下1/5左右。

退保之後如果還想使用健保( 比如:外國僑民),只能加保!所以,只要找出最後的加保日期,就可以推斷病人是否活著。

如果加了又退加了又退的呢?痾,那就真的很難知道到底是活著還是死掉,只要最後一次退保日期大於加保日期,就當他/她死了吧!

3. join 是個十分耗資源的工程,需要兩個東西來加快速度:

    1. Index 一定要設好!可以讓你30萬對50萬的查詢從10000 Sec跑不出來變成 30 sec 完工!

    2. 打不動大的,把你拆成小的總可以吧!

        從400萬依據時間區間拆成10份,每份30秒,5分鐘搞定!

4. Max 也是一個耗資源的工程,所以我們用拆分時間階層的方式,手動完成!

5. 少用!= (不等於),超耗資源又跑不動!剛講的30萬對50萬的查詢一整天跑不出來,

    用"=",兩張表 ( null 跟 not null 分開) 又是變成 30 sec 完工!

結論:


ID檔奮戰結束的當晚,除了一瞬間解決問題的快感以外,下一個瞬間突然覺得,收到壓死線的最後一批檔案後這一段跟ID檔死嗑的時間,不知道為了什麼?!

只為了得到較準確的相對死亡日期吧!我想!