1. 程式人生 > 其它 >資料查詢語言優化例項-20210104

資料查詢語言優化例項-20210104

技術標籤:資料庫資料庫資料分析sql

資料查詢語言優化例項-20210104

最近的實際工作中要參與一些資料彙總工作,因為工作內容不是特別的系統,寫的程式碼也不準備留給誰,所以一開始並沒有特別注重執行效率,只要執行不超過5分鐘的並沒有特別在意。

但工作能讓你這麼舒服嗎,顯然不可能。還是遇到了下面必須要盤(優化)的程式碼。

一 需要優化的語句

-- 執行效率:40分鐘以上沒有執行完
create table test_table as 
select
    '20210101' as STAT_DT 
    ,a1.CUST_ID as CUST_ID 
    ,a1.USER_LOAN_FLG as USER_LOAN_FLG 
    ,a1.SQ_LOAN_FLG as SQ_LOAN_FLG 
    ,a1.CURR_SQ_LOAN_FLG as CURR_SQ_LOAN_FLG 
    ,(case when a7.CIF_NO is not null then 1 else 0 end) as BLK_FLG 
    ,'0' as EMP_FLG 
    ,a1.EC_LOAN_FLG as EC_LOAN_FLG 
    ,a1.BAD_LOAN_FLG as BAD_LOAN_FLG  
    ,'0' as OD_LOAN_FLG 
    ,a2.AGE_CD as AGE_CD 
    ,a2.SEX_CD as SEX_CD 
    ,a2.DEPO_OPEN_DUR as DEPO_OPEN_DUR 
    ,a2.CROSS_ORG_CNT as CROSS_ORG_CNT 
    ,a2.DEPO_ACCT_CNT as DEPO_ACCT_CNT 
    ,a2.CURR_BAL as DEPO_BAL 
    ,a2.LOAN_BAL as LOAN_BAL 
    ,a2.CURR_BAL/a2.LOAN_BAL as DEPO_LOAN_RT 
    ,a4.DEPO_BAL_20191130 as DEPO_BAL_20191130 
    ,a5.M_AVG_DEPO_BAL as M_AVG_DEPO_BAL 
    ,a6.MAX_M_AVG_DEPO_BAL as MAX_M_AVG_DEPO_BAL 
    ,a6.MAX_M_AVG_DEPO_BAL_MCNT as MAX_M_AVG_DEPO_BAL_MCNT 
    ,(case when a10.CUST_ID is null then 1 else 0 end) as CARD_FLG 
    ,a1.LOAN_H_CNT as LOAN_H_CNT 
    ,(case when a8.master_cust_no is null then 0 else 1 end) as TIME_FLG 
    ,a9.M12_TRAN_AMT as M12_TRAN_AMT 
    ,a9.M12_TRAN_CNT as M12_TRAN_CNT 
    ,a9.M12_D_TRAN_AMT as M12_D_TRAN_AMT 
    ,a9.M12_C_TRAN_AMT as M12_C_TRAN_AMT 
    ,a9.M12_MAX_SIGLE_TRAN_AMT as M12_MAX_SIGLE_TRAN_AMT 
    ,a9.M12_D_MAX_SIGLE_TRAN_AMT as M12_D_MAX_SIGLE_TRAN_AMT 
    ,a9.M12_C_MAX_SIGLE_TRAN_AMT as M12_C_MAX_SIGLE_TRAN_AMT 
    ,(a2.CURR_BAL-a4.DEPO_BAL_20191130)/M12_C_TRAN_AMT as RETEN_RT 
    ,'0' as Y1 
    ,'0' as Y2 
    ,(case when a1.LOAN_H_CNT>1 and a2.LOAN_BAL>0 then 1 else 0 end) as Y3 
from (
    select 
        b1.CIF_ID as CUST_ID
        ,(CASE WHEN SUM(CASE WHEN b1.BEG_DATE BETWEEN 20171201 AND 20201130 THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) as USER_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.FIN_DATE BETWEEN 20191201 AND 20201130 THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) as SQ_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.DUE_STS='9' THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) as CURR_SQ_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.PRDT_NO IN ('C107','C118','C119','C120','C127','129','C130','C108','C112') THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) AS EC_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.FIVE_STS IN ('3','4','5') THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) AS BAD_LOAN_FLG
        ,SUM(CASE WHEN b1.BEG_DATE BETWEEN 20171201 AND 20201130 THEN 1 ELSE 0 END) AS LOAN_H_CNT
    from F_CMS_RPT_XD b1
    where CIF_ID like '010%'--個人客戶
    group by b1.CIF_ID
) a1
LEFT JOIN ANA_STRUCTURAL a2
ON a1.CUST_ID = a2.CUST_ID
-- LEFT JOIN
-- (
--     select CUST_NO as CUST_NO,sum(DUEBILL_BAL) as LOAN_BAL
--     from F_LN_LN_DUE_RECORD
--     where CUST_NO like '01%' and record_dt = '20201130'-- 取對私客戶
--     group by CUST_NO
-- ) a3 --借據月表
-- ON a1.CUST_ID = a3.CUST_NO
LEFT JOIN 
(
    select master_cust_no,sum(PRT_LED_BAL) as DEPO_BAL_20191130
    from ADPXX_CQ_RECORD
    where record_dt = '20191130' 
    group by master_cust_no
) a4 --存款賬戶月表
ON a1.CUST_ID = a4.master_cust_no
LEFT JOIN 
(
    select master_cust_no,sum(AVGBAL) as M_AVG_DEPO_BAL
    from ADPXX_AVG_ACCTNO
    where ym = '202011'
    group by master_cust_no
) a5 --歷史月日均記錄
ON a1.CUST_ID = a5.master_cust_no
LEFT JOIN 
(
    select 
        master_cust_no,AVG_MONTH as MAX_M_AVG_DEPO_BAL,
        months_between(to_date('202011','yyyymm'),to_date(ym,'yyyymm')) as MAX_M_AVG_DEPO_BAL_MCNT
    from ADPXX_MAXAVG_MASTER_CUST_NO 
) a6 --最高月日均記錄
ON a1.CUST_ID = a6.master_cust_no
LEFT JOIN 
(
    select distinct CIF_NO
    from F_CMS_CIF_BLACK_CAUSE 
) a7 --黑名單
ON a1.CUST_ID = a7.CIF_NO
LEFT JOIN 
(
    select distinct master_cust_no
    from ADPXX_CQ_RECORD
    where 
        (record_dt between 20171201 and 20201130) --近三年
        and LIAB_PRDT_TYPE = '1'--取定期
    group by master_cust_no
) a8 --取定期歷史記錄
ON a1.CUST_ID = a8.master_cust_no
LEFT JOIN 
(
    select 
        b2.MASTER_CUST_NO as CUST_ID
        ,SUM(b1.TX_AMT) as M12_TRAN_AMT 
        ,count(1) as M12_TRAN_CNT
        ,SUM(CASE WHEN b1.CR_DR_MAINT_IND = 0 THEN b1.TX_AMT ELSE 0 END) as M12_D_TRAN_AMT
        ,SUM(CASE WHEN b1.CR_DR_MAINT_IND = 1 THEN b1.TX_AMT ELSE 0 END) as M12_C_TRAN_AMT
        ,MAX(b1.TX_AMT) as M12_MAX_SIGLE_TRAN_AMT
        ,MAX(CASE WHEN b1.CR_DR_MAINT_IND = 0 THEN b1.TX_AMT ELSE 0 END) as M12_D_MAX_SIGLE_TRAN_AMT
        ,MAX(CASE WHEN b1.CR_DR_MAINT_IND = 1 THEN b1.TX_AMT ELSE 0 END) as M12_C_MAX_SIGLE_TRAN_AMT
    from F_CI_BDPAL b1
    left join ADPXX_CQ b2 
    on b1.acct_no = b2.acct_no
    where 
        b1.TX_DT BETWEEN 20191201 AND 20201130
        and b1.MEMO_CODE NOT IN ('000212','B00102','B00104','B10003') --入息、放貸、還息、還貸
        and (b1.RVS_FLG NOT IN ('1','2') OR b1.BRVS_FLG<>'1') --衝正和被衝正
    group by b2.MASTER_CUST_NO
) a9 --賬戶餘額發生明細表
ON  a1.CUST_ID = a9.CUST_ID
LEFT JOIN 
(
    select 
        distinct a2.kehhao as CUST_ID
    from F_CCS_CARD a1
    left join F_CI_BDSKH a2
    on trim(a1.CUSTR_NBR) = trim(a2.ZHJHAO)
    where a2.ZHJNZL = '10' and a1.CANCL_DAY <= 20201130 and a1.ISSUE_DAY <= 20201130
) a10
ON a1.CUST_ID = a10.CUST_ID
;

二 語句效率執行慢原因解析 以及 解決方式

  1. left join 的表太多

說一下left join 的演算法

解決方式:
根據業務類別和left join 表資料量的的不同,將程式碼拆分成幾部分。具體的實現方式就是建立中間表(臨時表),上述程式碼我拆分成了兩部分,第一部分為客戶的基本資訊以及一些容易算出的欄位指標,第二部分則為資料量龐大的交易明細彙總部分。

  1. left join 的一些表資料太大

解決方式:
我們這些資料量很大的表,我們可以通過加強where條件篩選出我們需要的資料,也可以直接將資料一次性彙總成我們需要的表。如上述程式碼中的 a9 表,表資料總數約2億,我們只提取固定1年時間仍然是很大的資料量,因此可以在此的基礎上在增加客戶號的篩選條件,以及增加索引。

  1. 語句中牽扯了大量的聚合函式

解決方式:
在建立中間表的過程中,已經將大部分的聚合函式執行完畢,因此在彙總最後結果時,兩張表只需要簡單的left join 即可。

  1. 其它

上述的解決方式都是大方向的優化,在具體的優化還可以補充以下方式:

  • 為中間表及需要的表建立索引,建立索引可以解決大部分的查詢效率問題;
  • 增加臨時表空間、分庫分表等操作也會增加資料的查詢效率,但在本次優化過程中並沒有使用,不做討論。

三 優化後代碼

------------------------------------------------------------------------------
-- 1. 客戶群主表
------------------------------------------------------------------------------
drop table ana_tmp_t1 ;
create table ana_tmp_t1 as
select 
    a1.CUST_ID as CUST_ID -- 客戶號
    ,a1.USER_LOAN_FLG as USER_LOAN_FLG -- 是否在20171201-20201130有過用信
    ,a1.SQ_LOAN_FLG as SQ_LOAN_FLG -- 是否在20191201-20201130結清貸款
    ,a1.CURR_SQ_LOAN_FLG as CURR_SQ_LOAN_FLG -- 當前是否結清客戶
    ,(case when a7.CIF_NO is not null then 1 else 0 end) as BLK_FLG -- 是否黑名單客戶
    ,a1.EC_LOAN_FLG as EC_LOAN_FLG -- 是否有過按揭貸款、貧困貸、助學貸
    ,a1.BAD_LOAN_FLG as BAD_LOAN_FLG -- 是否有過五級不良貸款
    ,a1.LOAN_H_YQDAY_MCNT as LOAN_H_YQDAY_MCNT -- 歷史最大逾期天數 -- 76 結清日期都為null
    ,a11.AGE_CD as AGE_CD -- 年齡 
    ,a11.SEX_CD as SEX_CD -- 性別 
    ,nvl2(a2.DEPO_OPEN_DUR,a2.DEPO_OPEN_DUR,0) as DEPO_OPEN_DUR -- 存款開戶時長 
    ,nvl2(a2.CROSS_ORG_CNT,a2.CROSS_ORG_CNT,0) as CROSS_ORG_CNT -- 跨網點數 
    ,nvl2(a2.DEPO_ACCT_CNT,a2.DEPO_ACCT_CNT,0) as DEPO_ACCT_CNT -- 存款賬戶數 
    ,nvl2(a2.CURR_BAL,a2.CURR_BAL,0) as DEPO_BAL -- 當前時點存款餘額
    ,a1.LOAN_BAL as LOAN_BAL -- 當前貸款餘額
    ,(case when a1.LOAN_BAL = 0 then -1 else nvl2(a2.CURR_BAL,a2.CURR_BAL,0)/a1.LOAN_BAL end ) as DEPO_LOAN_RT -- 當前存貸比 
    ,nvl2(a4.DEPO_BAL_20191130,a4.DEPO_BAL_20191130,0) as DEPO_BAL_20191130 -- 20191130時點餘額 
    ,nvl2(a5.M_AVG_DEPO_BAL,a5.M_AVG_DEPO_BAL,0) as M_AVG_DEPO_BAL -- 當前月日均存款
    ,nvl2(a6.MAX_M_AVG_DEPO_BAL,a6.MAX_M_AVG_DEPO_BAL,0) as MAX_M_AVG_DEPO_BAL -- 歷史最高月日均存款 
    ,nvl2(a6.MAX_M_AVG_DEPO_BAL_MCNT,a6.MAX_M_AVG_DEPO_BAL_MCNT,0) as MAX_M_AVG_DEPO_BAL_MCNT -- 歷史最高月日均存款距當前月份 
    ,(case when a10.CUST_ID is null then 1 else 0 end) as CARD_FLG -- 是否有信用卡產品
    ,a1.LOAN_H_CNT as LOAN_H_CNT -- 近3年貸款次數
    ,a1.BAD_DUE_FLG as BAD_DUE_FLG -- 是否有過借據不正常的借據
from
(
    select 
        b1.cif_no as CUST_ID
        ,(CASE WHEN SUM(CASE WHEN b1.BEG_DATE BETWEEN 20171201 AND 20201130 THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) as USER_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.due_sts='9' THEN 0 ELSE 1 END)=0 AND MAX(b1.FIN_DATE) >= 20191201 THEN 1 ELSE 0 END) as SQ_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.due_sts='9' THEN 0 ELSE 1 END)=0 THEN 1 ELSE 0 END) as CURR_SQ_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.PRDT_NO IN ('C107','C118','C119','C120','C127','129','C130','C108','C112','G101','G104','I103') THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) AS EC_LOAN_FLG
        ,(CASE WHEN SUM(CASE WHEN b1.FIVE_STS IN ('3','4','5') THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) AS BAD_LOAN_FLG
        ,SUM(CASE WHEN b1.BEG_DATE BETWEEN 20171201 AND 20201130 THEN 1 ELSE 0 END) AS LOAN_H_CNT
        ,(CASE WHEN SUM(CASE WHEN b1.due_sts not in ('1','9') THEN 1 ELSE 0 END)>0 THEN 1 ELSE 0 END) AS BAD_DUE_FLG -- 是否有過借據不正常的借據
        ,MAX(b1.LOAN_H_YQDAY_CNT) AS LOAN_H_YQDAY_MCNT -- 最大逾期天數
        ,SUM(BAL) as LOAN_BAL -- 當前貸款餘額
    from 
    (
        SELECT 
            c1.*
            ,(
                CASE 
                    WHEN c1.due_sts = '1' THEN (to_date('20201130','yyyymmdd') -to_date(c1.EXP_ENDDATE,'yyyymmdd')-1) 
                    WHEN c1.due_sts = '9' THEN (to_date(c1.FIN_DATE,'yyyymmdd')-to_date(c1.EXP_ENDDATE,'yyyymmdd')-1)
                    ELSE 99999
                END
            ) as LOAN_H_YQDAY_CNT
        from F_CMS_RPT_XD c1
        where c1.cif_no like '010%'--個人客戶
            -- and c1.FIN_DATE BETWEEN 20191201 AND 20201130
            -- and c1.PRDT_NO not in ('G101','G104','I103') -- 'I103':'公積金'
    ) b1
    group by b1.cif_no
) a1
LEFT JOIN ANA_STRUCTURAL a2
ON a1.CUST_ID = a2.CUST_ID
LEFT JOIN 
(
    select master_cust_no,sum(PRT_LED_BAL) as DEPO_BAL_20191130
    from ADPXX_CQ_RECORD
    where record_dt = '20191130' 
    group by master_cust_no
) a4 --存款賬戶月表
ON a1.CUST_ID = a4.master_cust_no
LEFT JOIN 
(
    select master_cust_no,sum(AVGBAL) as M_AVG_DEPO_BAL
    from ADPXX_AVG_ACCTNO
    where ym = '202011'
    group by master_cust_no
) a5 --歷史月日均記錄
ON a1.CUST_ID = a5.master_cust_no
LEFT JOIN 
(
    select 
        master_cust_no,AVG_MONTH as MAX_M_AVG_DEPO_BAL,
        months_between(to_date('202011','yyyymm'),to_date(ym,'yyyymm')) as MAX_M_AVG_DEPO_BAL_MCNT
    from ADPXX_MAXAVG_MASTER_CUST_NO 
) a6 --最高月日均記錄
ON a1.CUST_ID = a6.master_cust_no
LEFT JOIN 
(
    select distinct CIF_NO
    from F_CMS_CIF_BLACK_CAUSE 
) a7 --黑名單
ON a1.CUST_ID = a7.CIF_NO
LEFT JOIN 
(
    select 
        distinct a2.kehhao as CUST_ID
    from F_CCS_CARD a1
    left join F_CI_BDSKH a2
    on trim(a1.CUSTR_NBR) = trim(a2.ZHJHAO)
    where a2.ZHJNZL = '10' and a2.kehhao like '010%' and a1.CANCL_DAY <= 20201130 and a1.ISSUE_DAY <= 20201130
) a10
ON a1.CUST_ID = a10.CUST_ID
left join 
(
    select 
        c1.cif_no as CUST_ID,c2.id_no
        ,case 
            when isidcard_new(c2.id_no) = '1' then
                trunc(
                    months_between(
                        to_date('20201130','yyyymmdd'),
                        to_date(
                            case when length(trim(c2.id_no)) = 18 
                            then SubStr(c2.id_no, 7, 8) 
                            else '19' || SubStr(c2.id_no, 7, 6)
                            end , 'yyyymmdd'
                        )
                    )/12
                ) 
            else 999 end
        as AGE_CD
        ,case 
            when isidcard_new(c2.id_no) = '1' 
            then (
                case 
                    when length(trim(c2.id_no)) = 18 and mod(SubStr(c2.id_no, 17, 1),2) = 1 then '1' --男
                    when length(trim(c2.id_no)) = 18 and mod(SubStr(c2.id_no, 17, 1),2) = 0 then '2' --女
                    when length(trim(c2.id_no)) = 15 and mod(SubStr(c2.id_no, 15, 1),2) = 1 then '1' --男
                    when length(trim(c2.id_no)) = 15 and mod(SubStr(c2.id_no, 15, 1),2) = 0 then '2' --女
                else '999'
                end 
            ) else '999' end 
        as SEX_CD
    from
    (
        SELECT
            b1.cif_no,max(b1.beg_date) as x
        FROM F_CMS_RPT_XD b1
        where 
            CIF_NO like '010%'
        group by b1.cif_no
    ) c1
    left join
    (
        SELECT
            b1.cif_no,b1.id_no,max(b1.beg_date) as x
        FROM F_CMS_RPT_XD b1
        where 
            CIF_NO like '010%'
        group by b1.cif_no,b1.id_no
    ) c2
    on c1.cif_no = c2.cif_no and c1.x = c2.x
) a11 -- 對私客戶資訊表
on a1.CUST_ID = a11.CUST_ID
;
alter table ana_tmp_t1 add primary key (CUST_ID);

------------------------------------------------------------------------------
-- 2. 賬戶餘額發生明細表-資料彙總
------------------------------------------------------------------------------
drop table ana_tmp_t2;
create table ana_tmp_t2 as
select 
    b2.MASTER_CUST_NO as CUST_ID
    ,SUM(b1.TX_AMT) as M12_TRAN_AMT 
    ,count(1) as M12_TRAN_CNT
    ,SUM(CASE WHEN b1.CR_DR_MAINT_IND = 0 THEN b1.TX_AMT ELSE 0 END) as M12_D_TRAN_AMT
    ,SUM(CASE WHEN b1.CR_DR_MAINT_IND = 1 THEN b1.TX_AMT ELSE 0 END) as M12_C_TRAN_AMT
    ,MAX(b1.TX_AMT) as M12_MAX_SIGLE_TRAN_AMT
    ,MAX(CASE WHEN b1.CR_DR_MAINT_IND = 0 THEN b1.TX_AMT ELSE 0 END) as M12_D_MAX_SIGLE_TRAN_AMT
    ,MAX(CASE WHEN b1.CR_DR_MAINT_IND = 1 THEN b1.TX_AMT ELSE 0 END) as M12_C_MAX_SIGLE_TRAN_AMT
from F_CI_BDPAL b1
left join ADPXX_CQ b2 
on b1.acct_no = b2.acct_no
where 
    b1.TX_DT BETWEEN 20191201 AND 20201130
    AND( MEMO_CODE NOT IN ('000212','B00102','B00104','B10003') OR MEMO_CODE IS NULL) --入息、放貸、還息、還貸
    and (b1.RVS_FLG NOT IN ('1','2') OR b1.BRVS_FLG<>'1') --衝正和被衝正
group by b2.MASTER_CUST_NO
;
--alter table ana_tmp_t2 add primary key (CUST_ID);

------------------------------------------------------------------------------
-- 2.1. 賬戶餘額發生明細表-資料彙總
------------------------------------------------------------------------------
drop table ana_tmp_t3;
create table ana_tmp_t3 as
select 
    b2.MASTER_CUST_NO as CUST_ID
    ,sum(b1.TX_AMT) as M12_C_ALL_TRAN_AMT
from F_CI_BDPAL b1
left join ADPXX_CQ b2 
on b1.acct_no = b2.acct_no
where 
    b1.TX_DT BETWEEN 20191201 AND 20201130
    and (b1.RVS_FLG NOT IN ('1','2') OR b1.BRVS_FLG<>'1') --衝正和被衝正
    and b1.CR_DR_MAINT_IND = 1
group by b2.MASTER_CUST_NO
;

------------------------------------------------------------------------------
-- 3. 個人貸款客戶彙總表-資料彙總
------------------------------------------------------------------------------
drop table ANA_MARKETING_TMP ;
create table ANA_MARKETING_TMP as
select
    '20201130' as STAT_DT -- 統計日期
    ,a1.CUST_ID as CUST_ID -- 客戶號
    ,a1.USER_LOAN_FLG as USER_LOAN_FLG -- 是否在20171201-20201130有過用信
    ,a1.SQ_LOAN_FLG as SQ_LOAN_FLG -- 是否在20191201-20201130結清貸款
    ,a1.CURR_SQ_LOAN_FLG as CURR_SQ_LOAN_FLG -- 當前是否結清客戶
    ,a1.BLK_FLG as BLK_FLG -- 是否黑名單客戶
    ,'0' as EMP_FLG -- 是否本行員工
    ,a1.EC_LOAN_FLG as EC_LOAN_FLG -- 是否有過按揭貸款、貧困貸、助學貸
    ,a1.BAD_LOAN_FLG as BAD_LOAN_FLG -- 是否有過五級不良貸款
    ,a1.LOAN_H_YQDAY_MCNT as LOAN_H_YQDAY_MCNT -- 歷史最大逾期天數
    ,a1.AGE_CD as AGE_CD -- 年齡
    ,a1.SEX_CD as SEX_CD -- 性別
    ,a1.DEPO_OPEN_DUR as DEPO_OPEN_DUR -- 存款開戶時長
    ,a1.CROSS_ORG_CNT as CROSS_ORG_CNT -- 跨網點數
    ,a1.DEPO_ACCT_CNT as DEPO_ACCT_CNT -- 存款賬戶數
    ,a1.DEPO_BAL as DEPO_BAL -- 當前時點存款餘額
    ,a1.LOAN_BAL as LOAN_BAL -- 當前貸款餘額
    ,a1.DEPO_LOAN_RT as DEPO_LOAN_RT -- 當前存貸比
    ,a1.DEPO_BAL_20191130 as DEPO_BAL_20191130 -- 20191130時點餘額
    ,a1.M_AVG_DEPO_BAL as M_AVG_DEPO_BAL -- 當前月日均存款
    ,a1.MAX_M_AVG_DEPO_BAL as MAX_M_AVG_DEPO_BAL -- 歷史最高月日均存款
    ,a1.MAX_M_AVG_DEPO_BAL_MCNT as MAX_M_AVG_DEPO_BAL_MCNT -- 歷史最高月日均存款距當前月份
    ,a1.CARD_FLG as CARD_FLG -- 是否有信用卡產品
    ,a1.LOAN_H_CNT as LOAN_H_CNT -- 近3年貸款次數
    ,(case when a8.master_cust_no is null then 0 else 1 end) as TIME_FLG -- 歷史是否有定期產品
    ,nvl2(a9.M12_TRAN_AMT,a9.M12_TRAN_AMT,0) as M12_TRAN_AMT -- 近一年總交易金額
    ,nvl2(a9.M12_TRAN_CNT,a9.M12_TRAN_CNT,0) as M12_TRAN_CNT -- 近一年總交易筆數
    ,nvl2(a9.M12_D_TRAN_AMT,a9.M12_D_TRAN_AMT,0) as M12_D_TRAN_AMT -- 近一年借方總交易金額
    ,nvl2(a9.M12_C_TRAN_AMT,a9.M12_C_TRAN_AMT,0) as M12_C_TRAN_AMT -- 近一年貸方總交易金額
    ,nvl2(a9.M12_MAX_SIGLE_TRAN_AMT,a9.M12_MAX_SIGLE_TRAN_AMT,0) as M12_MAX_SIGLE_TRAN_AMT -- 近一年單筆最大交易金額
    ,nvl2(a9.M12_D_MAX_SIGLE_TRAN_AMT,a9.M12_D_MAX_SIGLE_TRAN_AMT,0) as M12_D_MAX_SIGLE_TRAN_AMT -- 近一年借方單筆最大交易金額
    ,nvl2(a9.M12_C_MAX_SIGLE_TRAN_AMT,a9.M12_C_MAX_SIGLE_TRAN_AMT,0) as M12_C_MAX_SIGLE_TRAN_AMT -- 近一年貸方單筆最大交易金額
    ,(case when nvl2(a10.M12_C_ALL_TRAN_AMT,a10.M12_C_ALL_TRAN_AMT,0) = 0 then -999999 else (a1.DEPO_BAL-a1.DEPO_BAL_20191130)/nvl2(a10.M12_C_ALL_TRAN_AMT,a10.M12_C_ALL_TRAN_AMT,0) end) as RETEN_RT -- 留存率
    ,'0' as Y1 -- 
    ,'0' as Y2 -- 
    ,(case when a1.LOAN_H_CNT>1 and a1.LOAN_BAL>0 then 1 else 0 end) as Y3 -- 是否近3年有過多次貸款且當前正在貸款的客戶
from 
(
    select * from ana_tmp_t1 where BAD_DUE_FLG = '0'
) a1
LEFT JOIN 
(
    select distinct master_cust_no
    from ADPXX_CQ_RECORD
    where 
        (record_dt between 20171201 and 20201130) --近三年
        and LIAB_PRDT_TYPE = '1'--取定期
    group by master_cust_no
) a8 --取定期歷史記錄
ON a1.CUST_ID = a8.master_cust_no
LEFT JOIN ana_tmp_t2 a9 
ON a1.CUST_ID = a9.CUST_ID
LEFT JOIN ana_tmp_t3 a10 
ON a1.CUST_ID = a10.CUST_ID
;
alter table ANA_MARKETING_TMP add primary key (CUST_ID);

四 結論

在實際工作中,優化查詢有時並不需要多麼先進的理論和技術,而是根據工作需求找準清晰的目標和問題所在(業務拆分、關鍵資訊提煉、資料整合),靈活使用基礎技術即可達到目的。