查找某天的交易链,建立二叉树

create or replace procedure sp_mid_game_trade_list is
/******************************************************************
      存储过程名称:
      存储过程内容:计算某天某个DB的交易链
      作者姓名: 
      编写时间: 2017年11月2日
      修改;            

      输入参数:
              v_date  --统计日期 (yyyy-mm-dd)
      输出参数:
      算法描述:
              
    *******************************************************************/
  cursor cur_1 is
    select distinct dbname, sell_roleid
      from game_empty_trad_list;
begin
  for rec_1 in cur_1 loop
    insert into game_TRAD_CONNECT_UN_list
      select /*+parallel(8)*/
       dt, LEVEL, rec_1.dbname, sell_roleid, buy_roleid, rec_1.sell_roleid, 0
        from game_empty_trad_list a
       start with sell_roleid = rec_1.sell_roleid
      -- AND dbname = rec_1.dbname
      connect by NOCYCLE prior buy_roleid = sell_roleid -- AND PRIOR dbname=dbname
      ;
    commit;
  
  ----return; -- 测试,只执行一个号
  end loop;
exception
  when others then
    rollback;
    
end sp_mid_game_trade_list;

 

create or replace procedure SP_game_TRAD_CONNECT_UN_LIST
as
/******************************************************************
      存储过程名称:
      存储过程内容:计算某天某个DB的交易链
      作者姓名: 
      编写时间: 2017年11月6日
      修改;            

      输入参数:
              v_date  --统计日期 (yyyy-mm-dd)
      输出参数:
      算法描述:
              
    *******************************************************************/
v_begin_date date;
v_db number;
v_date date;

cursor cur_db is 
         select distinct dbname from game_empty_trad_emoney_un 
         where record_date >= v_date-7;  -- 取7天内的DB         
         
         
begin

     v_date := trunc(sysdate)-1;
     --DATE'2017-10-18'; -- 开服第一天
      -- 

  
  dbms_output.put_line(v_date);
  
  --1、每条交易卖家 买家
--- 耗时 444
-- CREATE TABLE game_trad_sell_buy AS
delete from game_trad_sell_buy;
commit;

insert into game_trad_sell_buy
SELECT /*+parallel(8)*/ a.record_date,a.dbname,a.col_3,a.role_id sell_roleid,b.role_id buy_roleid,a.trad_num sell_num,b.trad_num buy_num
FROM
(
  SELECT row_number()OVER(PARTITION BY col_3 ORDER BY trad_num DESC)trad_rank,t.*
  FROM 
  (
    SELECT record_date,dbname,col_3,role_id,SUM(col_5+col_6+col_7+col_8)trad_num,SUM(col_6)trad_emoney_num
    FROM gameb_ods.game_bigtable_log a
    WHERE actiontype=21
          AND record_date<trunc(sysdate)  --当前日期
          and record_date>=v_date -- 取一周的数据
          -- to_date('2017-10-18 00:00:00','YYYY-MM-DD hh24:mi:SS') --游戏公测日期
    GROUP BY record_date,dbname,col_3,role_id
  )t
)a -- sell:trad_rank=1
LEFT JOIN 
(
  SELECT row_number()OVER(PARTITION BY col_3 ORDER BY trad_num DESC)trad_rank,t.*
  FROM 
  (
    SELECT col_3,role_id,SUM(col_5+col_6+col_7+col_8)trad_num,SUM(col_6)trad_emoney_num
    FROM gameb_ods.game_bigtable_log a
    WHERE actiontype=21
          AND record_date<trunc(sysdate)   --当前日期
          and record_date>=v_date -- 取一周的数据
    GROUP BY col_3,role_id

  )t
)b -- buy:trad_rank=2
ON a.col_3=b.col_3 AND a.trad_rank=b.trad_rank-1
WHERE a.trad_rank=1;
commit;

-----------------------------
--2、玩家交易魔石明细

delete from game_trad_sell_emoney;
commit;

insert into game_trad_sell_emoney
SELECT /*+parallel(8)*/ col_3,role_id,SUM(col_6)trad_emoney
FROM gameb_ods.game_bigtable_log a
WHERE actiontype=21
      AND record_date<trunc(sysdate) --当前日期
      and record_date>=v_date -- 取一周的数据
GROUP BY col_3,role_id;
commit;


--3、玩家空交易明细
delete from game_empty_trad;
commit;

insert into game_empty_trad
SELECT t.*,CASE WHEN sell_emoney=0 THEN 'item_empty'  WHEN sell_emoney=sell_num THEN 'emoney_empty' ELSE 'ALL_empty' END AS empty_type
FROM
(
  SELECT a.*,b.trad_emoney sell_emoney 
  FROM
  (
    SELECT *
    FROM game_trad_sell_buy
    WHERE buy_num=0
  )a
  LEFT JOIN 
  game_trad_sell_emoney b
  ON a.col_3=b.col_3 AND a.sell_roleid=b.role_id
)t;
commit;

--3.1、玩家魔石空交易明细
delete from game_empty_trad_emoney;
commit;

insert into game_empty_trad_emoney
SELECT *
from game_empty_trad
WHERE empty_type!='item_empty';
commit;



--4、异常玩家
--4.1、玩家角色表
--4.1.1、角色表
delete from game_user;
commit;

insert into game_user
    SELECT /*+parallel(8)*/ record_date,dbname,account_id,role_id,r_level,battle_lev,vip_lev,emoney emoney_save
    FROM
    (
    SELECT t.*,row_number()OVER(PARTITION BY dbname,account_id,role_id ORDER BY last_login_time DESC)save_rank
    FROM gameb_ods.game_user t
    WHERE record_date< trunc(sysdate)      --当前日期
          and record_date>=v_date -- 取一周的数据
    )t;
commit;

--4.1.2、角色消耗表  
--4.1.2.1、导出消耗表
delete from game_action15;
commit;

INSERT INTO game_action15
    SELECT /*+parallel(8)*/ *
    from gameB_ODS.game_BIGTABLE_LOG t
    WHERE record_date<trunc(sysdate)  --当前日期
    and record_date>=v_date -- 取一周的数据
    AND actiontype=15;
COMMIT;


--4.1.2.2、生成角色消耗表

delete from game_user_emoneycost;
commit;

INSERT INTO game_user_emoneycost
    SELECT /*+parallel(8)*/ dbname,account_id,role_id,SUM(col_4)emoney_cost
    from game_action15 t
    WHERE record_date<trunc(sysdate)  --当前日期
    and record_date>=v_date -- 取一周的数据
    GROUP BY dbname,account_id,role_id;
COMMIT;


--4.1.3、玩家角色表  
delete from game_user_info;
COMMIT;

INSERT INTO game_user_info
SELECT /*+parallel(8)*/ a.*,b.emoney_cost
FROM game_user a
LEFT JOIN game_user_emoneycost b
ON a.dbname=b.dbname AND a.role_id=b.role_id;
COMMIT;


--4.2、异常玩家定义
--低消耗低等级:等级低于79级,魔石存点大于10000,且魔石无消耗或魔石消耗率低(累计消耗魔石/魔石存点<0.1--高额空交易:单日累计空交易大于10万;
--大量空交易:空交易次数大于2或者单笔空交易大于10000

--------------------------
-- 删除异常数据
delete 
  FROM  game_user_info  t
  where t.account_id is null
  AND record_date>=v_date;
  
  commit;
--------------------------

--4.2.1、空交易次数玩家

delete from game_empty_trad_roleidcnt;
COMMIT;

INSERT INTO game_empty_trad_roleidcnt
  SELECT /*+parallel(8)*/ dbname,roleid,COUNT(1)empty_cnt,SUM(sell_emoney)sell_emoney
  FROM
  (
    SELECT dbname,sell_roleid roleid,sell_emoney
    from game_empty_trad
    WHERE empty_type!='item_empty'
  )t
  GROUP BY dbname,roleid;
COMMIT;



--4.2.3、低消耗用户
delete from game_user_info_type_tmp;
COMMIT;

INSERT INTO game_user_info_type_tmp 
SELECT /*+parallel(8)*/ a.*,'异常玩家'user_type,'低消耗低等级' reason_type
FROM
(
  SELECT t.*,
  (case emoney_save 
    when '0' then 100.0
      else emoney_cost*1.0/emoney_save 
        end) as cost_pec
  FROM  game_user_info  t
  where t.record_date = trunc(sysdate)-1  -- 昨天的日志
)a
WHERE r_level<79 AND round(emoney_save)>9999 AND cost_pec<0.1;
COMMIT;



--4.2.4、单日累计空交易大于10万

INSERT INTO game_user_info_type_tmp 
SELECT record_date,dbname,account_id,role_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,(emoney_cost+1)*1.0/(emoney_save+1) cost_pec,'异常玩家'user_tpye ,'高额空交易' reason_type
FROM
(
  SELECT /*+parallel(8)*/ a.*,b.roleid type_role,c.user_type
  FROM game_user_info  a
  LEFT JOIN 
  (SELECT dbname,roleid FROM game_empty_trad_roleidcnt WHERE  sell_emoney>=100000 ) b
  ON a.dbname=b.dbname AND a.role_id=b.roleid
  LEFT JOIN  game_user_info_type_tmp  c
  ON a.dbname=c.dbname AND a.role_id=c.role_id
  where a.record_date = trunc(sysdate)-1
)
WHERE type_role IS NOT NULL AND user_type IS  NULL;
commit;



--4.2.5、大量空交易

INSERT INTO game_user_info_type_tmp 
SELECT /*+parallel(8)*/ record_date,dbname,account_id,role_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,(emoney_cost+1)*1.0/(emoney_save+1) cost_pec,'疑似作弊'user_tpye ,'大量空交易' reason_type
FROM
(
  SELECT a.*,b.roleid type_role,c.user_type
  FROM game_user_info  a
  LEFT JOIN 
  (SELECT dbname,roleid FROM game_empty_trad_roleidcnt WHERE empty_cnt>=2 OR (empty_cnt=1 AND sell_emoney>=10000 )) b
  ON a.dbname=b.dbname AND a.role_id=b.roleid
  LEFT JOIN  game_user_info_type_tmp  c
  ON a.dbname=c.dbname AND a.role_id=c.role_id
  where a.record_date = trunc(sysdate)-1
)
WHERE type_role IS NOT NULL AND user_type IS  NULL;
commit;


--4.2.6、存档丢失问题解决--高额空交易

INSERT INTO game_user_info_type_tmp 
SELECT /*+parallel(8)*/ record_date,dbname,account_id,roleid role_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,(emoney_cost+1)*1.0/(emoney_save+1) cost_pec,'疑似作弊'user_tpye,'高额空交易' reason_type
FROM
(
  SELECT a.*,c.record_date,account_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,cost_pec,USER_TYPE
  from
  (
    SELECT * 
    FROM game_empty_trad_roleidcnt 
    WHERE  sell_emoney>=100000 
  )a
  LEFT JOIN  game_user_info_type_tmp  c
  ON a.dbname=c.dbname AND a.roleid=c.role_id
)t
WHERE user_type IS NULL;
commit;

--4.2.7、存档丢失问题解决--大量空交易
INSERT INTO game_user_info_type_tmp 
SELECT /*+parallel(8)*/ record_date,dbname,account_id,roleid role_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,(emoney_cost+1)*1.0/(emoney_save+1) cost_pec,'疑似作弊'user_tpye,'大量空交易' reason_type
FROM
(
  SELECT a.*,c.record_date,account_id,r_level,battle_lev,vip_lev,emoney_save,emoney_cost,cost_pec,USER_TYPE
  from
  (
    SELECT * 
    FROM game_empty_trad_roleidcnt 
    WHERE empty_cnt>=2 OR (empty_cnt=1 AND sell_emoney>=10000 )
  )a
  LEFT JOIN  game_user_info_type_tmp  c
  ON a.dbname=c.dbname AND a.roleid=c.role_id
)t
WHERE user_type IS NULL;
commit;

-- 把上面的计算结果去重,之前不想用merge into,是避免效率问题
delete from game_user_info_type;
COMMIT;

INSERT INTO game_user_info_type
select distinct  * from game_user_info_type_tmp;
commit;


--5、异常帐号链条抓取
--5.1、异常帐号相关交易
delete from game_empty_trad_emoney_un;
commit;

INSERT INTO game_empty_trad_emoney_un
SELECT /*+parallel(8)*/ record_date,dbname,col_3,sell_roleid,buy_roleid,sell_num,buy_num,sell_emoney,empty_type,sell_user_type,buy_user_type
FROM
(
  SELECT /*+PARALLEL(8)*/ a.*,b.user_type sell_user_type,c.user_type buy_user_type
  FROM game_empty_trad_emoney a
  LEFT JOIN game_user_info_type  b
  ON a.dbname=b.dbname AND a.sell_roleid=b.role_id
  LEFT JOIN game_user_info_type  c
  ON a.dbname=c.dbname AND a.buy_roleid=c.role_id
)
WHERE sell_user_type IS NOT NULL;
COMMIT;

--5.2、源头帐号
delete from game_trad_base_un;
commit;

INSERT INTO game_trad_base_un
SELECT /*+PARALLEL(8)*/ a.*,b.buy_roleid
FROM 
(
  SELECT DISTINCT dbname,sell_roleid
  FROM game_empty_trad_emoney_un t
)a
LEFT JOIN 
(  
  SELECT DISTINCT dbname,buy_roleid
  FROM game_empty_trad_emoney_un 
)b
ON a.dbname=b.dbname AND a.sell_roleid=b.buy_roleid
WHERE b.buy_roleid IS NULL;
COMMIT;

-- 开始循环计算每天的交易链
 while v_date <= trunc(sysdate) loop
     
   -- 删除关系链结果表特定日期的数据
   delete from game_TRAD_CONNECT_UN_LIST where dt = v_date;
   commit; 
   
   DBMS_OUTPUT.PUT_LINE(sysdate || '  ' || v_date);
   -- 只有某个区服的帐号,减少遍历
      for c_row in cur_db loop    
        --DBMS_OUTPUT.PUT_LINE(sysdate || '  ' || C_ROW.dbname);
        
        -- 清空临时表
        delete from game_empty_trad_list;
        commit; 
        -- 把某天某个服的数据插入临时表
        insert into game_empty_trad_list
          select distinct trunc(t.record_date) as dt,t.dbname, t.sell_roleid, t.buy_roleid
          from game_empty_trad_emoney_un t 
          where t.record_date >= v_date and t.record_date < v_date+1 
          and t.dbname = c_row.dbname;
        commit;
          
          -- 开始计算每天交易链
          sp_mid_game_trade_list;
          
          ----return; -- 测试一天一个DB的数据
       end loop;
       
       -- 标识当天交易链的最后一级
          merge into game_TRAD_CONNECT_UN_LIST t3
            using (
            select base_roleid,max(con_level) max_con_level from game_TRAD_CONNECT_UN_LIST
            where dt = v_date
            group by base_roleid
            ) t2
            on (t3.base_roleid = t2.base_roleid and t3.con_level = max_con_level)
            when matched then
              update set t3.is_max_level = 1;
            commit;
            
        v_date := v_date + 1;
    end loop;

     --- SP_ETL_ERROR_LOGS_PRO('ks_kill_sp_timeout','timeout',to_char(sysdate,'yyyymmdd'),v_txt);

end SP_game_TRAD_CONNECT_UN_LIST;

 

posted on 2019-02-27 17:41  凌度  阅读(87)  评论(0)    收藏  举报