Quellcode durchsuchen

修改内容:投手游戏总数据总计接口

lth vor 1 Jahr
Ursprung
Commit
5efc045c05

+ 399 - 33
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PitcherDataServiceImpl.java

@@ -21,11 +21,15 @@ import org.nutz.dao.pager.Pager;
 import org.nutz.dao.sql.Criteria;
 import org.nutz.dao.sql.Sql;
 import org.nutz.dao.util.Daos;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import reactor.util.function.Tuple2;
 import reactor.util.function.Tuples;
 
+import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
@@ -289,9 +293,9 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
             dto.setAmountEndDate(LocalDate.now());
         }
         //主表查询条件
-        Criteria criA = myCri(dto, "criA");
+        Criteria criA = myCri(dto, "criA", true);
         //账面相关查询条件 时间条件只和充值时间相关
-        Criteria criB = myCri(dto, "criB");
+        Criteria criB = myCri(dto, "criB", true);
         //账面人数相关 时间只需要充值时间条件,不需要注册时间条件
         Criteria criAmount = myCriRecharge(dto, false);
         //新用户充值人数和新用户复充人数 时间条件需要注册时间和充值时间
@@ -362,7 +366,6 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
             return vo;
         }).collect(Collectors.toList());
 
-
         //返回list结果封装到page对象里
         return new Page<>(pitcherGameDataTotalVOList, pager);
     }
@@ -374,7 +377,221 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
      */
     @Override
     public PitcherGameDataTotalSumVO getPitcherGameDataTotalSum(PitcherGameDataTotalSumDTO dto) {
-        return null;
+        //如果注册时间参数为空,默认设置查询当天数据
+        if (dto.getBeginDate() == null || dto.getEndDate() == null) {
+            dto.setBeginDate(LocalDate.now());
+            dto.setEndDate(LocalDate.now());
+        }
+        //如果充值时间参数为空,默认设置查询当天数据
+        if (dto.getAmountBeginDate() == null || dto.getAmountEndDate() == null) {
+            dto.setAmountBeginDate(LocalDate.now());
+            dto.setAmountEndDate(LocalDate.now());
+        }
+        //复制PitcherGameDataTotalSumDTO 到PitcherGameDataTotalDTO
+        PitcherGameDataTotalDTO totalDTO = new PitcherGameDataTotalDTO();
+        copyNullProperties(dto, totalDTO);
+        //主表查询条件
+        Criteria criA = myCri(totalDTO, "criA", false);
+        //账面相关查询条件 时间条件只和充值时间相关
+        Criteria criB = myCri(totalDTO, "criB", false);
+        //账面人数相关 时间只需要充值时间条件,不需要注册时间条件
+        Criteria criAmount = myCriRecharge(totalDTO, false);
+        //新用户充值人数和新用户复充人数 时间条件需要注册时间和充值时间
+        Criteria criNewUser = myCriRecharge(totalDTO, true);
+        //创角人数查询条件
+        Criteria criRoleNum = myCriRole(totalDTO);
+        //创建sql语句 执行sql
+        Sql sql = Sqls.create(pitcherGameDataTotalSumSql() + criA);
+        //设置自定义回显对象
+        sql.setCallback(Sqls.callback.entity());
+        sql.setEntity(dao.getEntity(PitcherGameDataTotalSumVO.class));
+        //执行sql
+        dao.execute(sql);
+        //得到结果
+        PitcherGameDataTotalSumVO vo = sql.getObject(PitcherGameDataTotalSumVO.class);
+        //得到账面相关数据、账面人数、新用户人数、新用户复充人数、创角人数数据
+        PitcherGameDataTotalSumVO tempVO = getPitcherGameDataTotalSumAmountData(criB, criAmount, criNewUser, criRoleNum);
+        //合并两个对象
+        copyNullProperties(tempVO, vo);
+
+        //计算相关指标
+        //新用户充值成本
+        vo.setNewUserAmountCost(vo.getNewUserAmountNum() == 0L ? BigDecimal.ZERO :
+                vo.getCost().divide(BigDecimal.valueOf(vo.getNewUserAmountNum()), 2, RoundingMode.HALF_UP));
+        //新用户付费率
+        vo.setNewUserAmountRate(vo.getRegisterNum() == 0L ? BigDecimal.ZERO :
+                BigDecimal.valueOf(vo.getNewUserAmountNum().doubleValue() / vo.getRegisterNum().doubleValue()).setScale(4, RoundingMode.HALF_UP));
+        //新用户付费比
+        vo.setNewUserAmountRatio(vo.getAmountNum() == 0L ? BigDecimal.ZERO :
+                BigDecimal.valueOf(vo.getNewUserAmountNum().doubleValue() / vo.getAmountNum().doubleValue()).setScale(4, RoundingMode.HALF_UP));
+        //新用户复充率
+        vo.setNewUserAgainRate(vo.getNewUserTotalAmountNum() == 0L ? BigDecimal.ZERO :
+                BigDecimal.valueOf(vo.getNewUserOrderAgain().doubleValue() / vo.getNewUserTotalAmountNum().doubleValue()).setScale(4, RoundingMode.HALF_UP));
+        //创角率
+        vo.setRoleNumRate(vo.getRegisterNum() == 0L ? BigDecimal.ZERO :
+                BigDecimal.valueOf(vo.getRoleNum().doubleValue() / vo.getRegisterNum().doubleValue()).setScale(4, RoundingMode.HALF_UP));
+        //创角成本
+        vo.setRoleNumCost(vo.getRoleNum() == 0L ? BigDecimal.ZERO :
+                vo.getCost().divide(BigDecimal.valueOf(vo.getRoleNum()), 2, RoundingMode.HALF_UP));
+
+        //获取所有筛选条件内的dayN数据
+        String dayNStr = tempDayNDataTotal(totalDTO);
+        //新用户充值金额
+        vo.setNewUserAmount(new BigDecimal(dayNStr.split("-")[0]));
+        //新用户充值次数
+        vo.setNewUserAmountCount(Long.parseLong(dayNStr.split("-")[1]));
+        //老用户充值人数、次数、金额
+        vo.setOldAmount(vo.getAmount().subtract(vo.getNewUserAmount()));
+        vo.setOldAmountCount(vo.getAmountCount() - vo.getNewUserAmountCount());
+        vo.setOldAmountNum(vo.getAmountNum() - vo.getNewUserAmountNum());
+        //新用户回收率
+        vo.setNewUserRoi(vo.getCost().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
+                vo.getNewUserAmount().divide(vo.getCost(), 4, RoundingMode.HALF_UP));
+        //新用户客单价
+        vo.setNewUserAvg(vo.getNewUserAmountCount() == 0L ? BigDecimal.ZERO :
+                vo.getNewUserAmount().divide(BigDecimal.valueOf(vo.getNewUserAmountCount()), 4, RoundingMode.HALF_UP));
+        //新用户ARPU
+        vo.setNewUserArpu(vo.getNewUserAmountNum() == 0L ? BigDecimal.ZERO :
+                vo.getNewUserAmount().divide(BigDecimal.valueOf(vo.getNewUserAmountNum()), 4, RoundingMode.HALF_UP));
+
+        //结果
+        return vo;
+    }
+
+    /**
+     * 得到账面相关数据、账面人数、新用户人数、新用户复充人数、创角人数数据
+     * @param criAmount 账面数据相关查询条件
+     * @return PitcherGameDataTotalSumVO
+     */
+    private PitcherGameDataTotalSumVO getPitcherGameDataTotalSumAmountData(Criteria criB, Criteria criAmount, Criteria criNewUser, Criteria criRoleNum) {
+        //得到账面相关数据
+        Sql sqlAmountData = Sqls.create("""
+                SELECT
+                    IFNULL(SUM(amount), 0) as amount,
+                    IFNULL(SUM(amount_count), 0) as amount_count,
+                    ROUND(IF(SUM(amount_count) > 0 , SUM(amount) / SUM(amount_count), 0), 2) as paper_avg
+                FROM
+                    game_ads.ads_game_pitcher_day
+                """ + criB);
+        //设置回传对象
+        sqlAmountData.setCallback(Sqls.callback.entity());
+        sqlAmountData.setEntity(dao.getEntity(PitcherGameDataTotalSumVO.class));
+        //执行sql
+        dao.execute(sqlAmountData);
+        PitcherGameDataTotalSumVO vo = sqlAmountData.getObject(PitcherGameDataTotalSumVO.class);
+
+        //账面人数数据
+        Sql sqlAmountNum = Sqls.create("""
+                SELECT
+                    IFNULL(COUNT(DISTINCT user_id), 0) amount_num
+                FROM
+                    game_ads.ads_information
+                """ + criAmount +
+                """
+                AND NOT agent_id = 0
+                """);
+        //设置回传对象
+        sqlAmountNum.setCallback(Sqls.callback.longValue());
+        //执行sql
+        dao.execute(sqlAmountNum);
+        //设置账面充值人数
+        vo.setAmountNum(sqlAmountNum.getLong());
+        //账面ARPU
+        vo.setPaperArpu(vo.getAmountNum() == 0L ? BigDecimal.ZERO :
+                vo.getAmount().divide(BigDecimal.valueOf(vo.getAmountNum()), 2, RoundingMode.HALF_UP));
+
+        //新用户充值人数
+        Sql sqlNewUserNum = Sqls.create("""
+                SELECT
+                    COUNT(DISTINCT user_id) new_user_amount_num
+                FROM
+                    game_ads.ads_information
+                """ + criNewUser +
+                """
+                AND NOT agent_id = 0
+                """);
+        //设置回传对象
+        sqlNewUserNum.setCallback(Sqls.callback.longValue());
+        //执行sql
+        dao.execute(sqlNewUserNum);
+        //设置新用户充值人数
+        vo.setNewUserAmountNum(sqlNewUserNum.getLong());
+
+        //新用户复充人数
+        Sql sqlNewUserAgainNum = Sqls.create("""
+                SELECT
+                    COUNT(tempA.num) as new_user_order_again
+                FROM (
+                    SELECT
+                        COUNT(user_id) num
+                    FROM
+                        game_ads.ads_information
+                    """ + criNewUser +
+                    """
+                    AND NOT agent_id = 0
+                    GROUP BY user_id
+                    HAVING
+                        COUNT(user_id) > 1 ) tempA
+                """);
+        //设置回传对象
+        sqlNewUserAgainNum.setCallback(Sqls.callback.longValue());
+        //执行sql
+        dao.execute(sqlNewUserAgainNum);
+        //设置新用户充值人数
+        vo.setNewUserOrderAgain(sqlNewUserAgainNum.getLong());
+
+        //创角人数
+        Sql sqlRoleNum = Sqls.create("""
+                SELECT
+                    COUNT(DISTINCT role_user_id) as role_num
+                FROM
+                    dw_create_role_detail
+                """ + criRoleNum +
+                """
+                AND NOT user_agent_id = 0
+                """);
+        //设置回传对象
+        sqlRoleNum.setCallback(Sqls.callback.longValue());
+        //执行sql
+        dao.execute(sqlRoleNum);
+        //设置创角人数
+        vo.setRoleNum(sqlRoleNum.getLong());
+
+        return vo;
+    }
+
+    /**
+     * 所有为空值的属性都不copy
+     *
+     * @param source 原数据
+     * @param target 目标数据
+     */
+    private void copyNullProperties(Object source, Object target) {
+        BeanUtils.copyProperties(source, target, getNullField(source));
+    }
+
+    /**
+     * 获取属性中为空的字段
+     *
+     * @param target 目标对象
+     * @return 不需要替换的字段数组
+     */
+    private static String[] getNullField(Object target) {
+        BeanWrapper beanWrapper = new BeanWrapperImpl(target);
+        PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
+        Set<String> notNullFieldSet = new HashSet<>();
+        if (propertyDescriptors.length > 0) {
+            for (PropertyDescriptor p : propertyDescriptors) {
+                String name = p.getName();
+                Object value = beanWrapper.getPropertyValue(name);
+                if (Objects.isNull(value)) {
+                    notNullFieldSet.add(name);
+                }
+            }
+        }
+        String[] notNullField = new String[notNullFieldSet.size()];
+
+        return notNullFieldSet.toArray(notNullField);
     }
 
     /**
@@ -382,9 +599,10 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
      *
      * @param dto  前端传递的查询条件
      * @param type criA 查询主表  criB 查询账面相关
+     * @param needGroupBy 是否需要分组条件
      * @return 查询条件
      */
-    private Criteria myCri(PitcherGameDataTotalDTO dto, String type) {
+    private Criteria myCri(PitcherGameDataTotalDTO dto, String type, Boolean needGroupBy) {
         //根据传入的dto拼接查询参数
         Criteria cri = Cnd.cri();
         if (StringUtils.isNotBlank(dto.getGameId())) {
@@ -420,7 +638,9 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
             }
         }
         //拼接分组条件
-        cri.getGroupBy().groupBy("game_id", "pitcher_id");
+        if (needGroupBy) {
+            cri.getGroupBy().groupBy("game_id", "pitcher_id");
+        }
 
         return cri;
     }
@@ -579,6 +799,62 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
         return tempMap;
     }
 
+    /**
+     * 计算所有的dayN
+     *
+     * @param dto       前端查询参数
+     * @return Map
+     */
+    private String tempDayNDataTotal(PitcherGameDataTotalDTO dto) {
+        //创建查询条件
+        Criteria cri = Cnd.cri();
+        if (dto.getBeginDate() != null && dto.getEndDate() != null) {
+            //拼接注册时间查询条件
+            cri.where().andBetween("dt", dto.getBeginDate(), dto.getEndDate());
+        }
+        if (StringUtils.isNotBlank(dto.getGameId())) {
+            //拼接游戏ID查询条件
+            cri.where().andEquals("game_id", dto.getGameId());
+        }
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            //拼接SDK来源查询条件
+            cri.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (dto.getPitcherId() != null) {
+            cri.where().andEquals("pitcher_id", dto.getPitcherId());
+        }
+        Sql dayNSql = Sqls.create("""
+                SELECT
+                    dt,
+                    game_id,
+                    pitcher_id,
+                    source_system,
+                    dayN
+                FROM
+                    game_ads.ads_pitcher_game_dayn
+                """ + cri);
+
+        //设置回传
+        dayNSql.setCallback(Sqls.callback.entities());
+        dayNSql.setEntity(dao.getEntity(AdsPitcherGameDayn.class));
+        //执行sql 获取数据到list中
+        dao.execute(dayNSql);
+
+        //将数据库中获取的所有结果封装到一个List中
+        List<AdsPitcherGameDayn> list = dayNSql.getList(AdsPitcherGameDayn.class);
+        //初始化dayN结果
+        Map<String, String> resMap = new HashMap<>();
+        resMap.put("dayN", "0.00-0");
+
+        //循环遍历 list 按照 gameId 进行存储
+        for (AdsPitcherGameDayn adsPitcherGameDayn : list) {
+            //解析每个 adsPitcherGameDayn 的 dayN
+            parseJsonData(adsPitcherGameDayn, resMap, dto);
+        }
+        //返回结果
+        return resMap.get("dayN");
+    }
+
     /**
      * 解析dayN json字符串数据
      *
@@ -601,14 +877,23 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
             if (DateUtil.parseLocalDate(key).compareTo(dto.getAmountBeginDate()) >= 0
                     && DateUtil.parseLocalDate(key).compareTo(dto.getAmountEndDate()) <= 0) {
                 //获取原先的dayN的值
-                String[] oldValues = resMap.get(adsPitcherGameDayn.getGameId()).split("-");
+                String[] oldValues;
+                if (resMap.containsKey("dayN")) {
+                    oldValues = resMap.get("dayN").split("-");
+                } else {
+                    oldValues = resMap.get(adsPitcherGameDayn.getGameId()).split("-");
+                }
                 //充值的金额
                 BigDecimal chargeMoney = new BigDecimal(oldValues[0]).add(new BigDecimal(resValues[0])).setScale(2, RoundingMode.HALF_UP);
                 //充值的次数
                 long count = Long.parseLong(oldValues[1]) + Long.parseLong(resValues[1]);
                 //合并成字符串 更新dayN的值
                 String newValue = chargeMoney + "-" + count;
-                resMap.put(adsPitcherGameDayn.getGameId(), newValue);
+                if (resMap.containsKey("dayN")) {
+                    resMap.put("dayN", newValue);
+                } else {
+                    resMap.put(adsPitcherGameDayn.getGameId(), newValue);
+                }
             }
         }
     }
@@ -1128,6 +1413,11 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
 
     /**
      * 查询投手游戏总数据SQL
+     * @param criA       主表查询条件
+     * @param criB       账面相关查询条件
+     * @param criAmount  账面充值人数查询条件
+     * @param criNewUser 新用户相关查询条件
+     * @param criRoleNum 创角人数相关查询条件
      * @return String
      */
     private String pitcherGameDataTotalSql(Criteria criA, Criteria criB, Criteria criAmount, Criteria criNewUser, Criteria criRoleNum) {
@@ -1234,11 +1524,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 		ROUND(IF(SUM(cost) > 0 , SUM(total) / SUM(cost), 0), 4) as roi_total
                 	FROM
                 		game_ads.ads_game_pitcher_day
-                	WHERE
-                		source_system='ZX_ONE'
-                		AND dt BETWEEN '2023-08-15' AND '2023-08-16'
-                	GROUP BY
-                		game_id,pitcher_id
+                	""" + criA +
+                    """
                 ) a
                 LEFT JOIN (
                 	SELECT
@@ -1249,11 +1536,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 	    ROUND(IF(SUM(amount_count) > 0 , SUM(amount) / SUM(amount_count), 0), 2) as paper_avg
                 	FROM
                 	    game_ads.ads_game_pitcher_day
-                	WHERE
-                		source_system = 'ZX_ONE'
-                		AND dt BETWEEN '2023-08-15' AND '2023-08-16'
-                	GROUP BY
-                		pitcher_id , game_id
+                	""" + criB +
+                    """
                 ) b ON a.pitcher_id = b.b_pitcher_id AND a.game_id = b.b_game_id
                 LEFT JOIN (
                 	SELECT
@@ -1262,9 +1546,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 		IFNULL(COUNT(DISTINCT user_id), 0) amount_num
                 	FROM
                 		game_ads.ads_information
-                	WHERE
-                	    source_system = 'ZX_ONE' AND
-                	    order_time BETWEEN '2023-08-15' AND '2023-08-16'
+                	""" + criAmount +
+                    """
                 	    AND NOT agent_id = 0
                 	GROUP BY pitcher_id , game_id
                 ) c ON a.pitcher_id = c.c_pitcher_id AND a.game_id = c.c_game_id
@@ -1275,10 +1558,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 		COUNT(DISTINCT user_id) new_user_amount_num
                 	FROM
                 		game_ads.ads_information
-                	WHERE
-                		source_system = 'ZX_ONE' AND
-                		order_time BETWEEN '2023-08-15' AND '2023-08-16'
-                		AND reg_time BETWEEN '2023-08-15' AND '2023-08-16'
+                	""" + criNewUser +
+                    """
                 		AND NOT agent_id = 0
                 	GROUP BY
                 		pitcher_id , game_id
@@ -1295,10 +1576,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 			COUNT(user_id) num
                 		FROM
                 			game_ads.ads_information
-                		WHERE
-                			source_system = 'ZX_ONE' AND
-                			order_time BETWEEN '2023-08-15' AND '2023-08-16'
-                			AND reg_time BETWEEN '2023-08-15' AND '2023-08-16'
+                		""" + criNewUser +
+                        """
                 			AND NOT agent_id = 0
                 		GROUP BY
                 			user_id,
@@ -1316,10 +1595,8 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 		COUNT(DISTINCT role_user_id) as role_num
                 	FROM
                 		dw_create_role_detail
-                	WHERE
-                		source_system = 'ZX_ONE' AND
-                		user_dt  BETWEEN '2023-08-15' AND '2023-08-16'
-                		AND DATE(role_create_time) BETWEEN '2023-08-15' AND '2023-08-16'
+                	""" + criRoleNum +
+                    """
                 		AND NOT user_agent_id = 0
                 	GROUP BY
                 		user_game_id, user_zx_pitcher_id
@@ -1327,5 +1604,94 @@ public class PitcherDataServiceImpl implements IPitcherDataService {
                 """;
     }
 
+    /**
+     * 查询投手游戏总数据总计SQL
+     *
+     * @return String
+     */
+    private String pitcherGameDataTotalSumSql() {
+        return """
+                SELECT
+                    IFNULL(SUM(cost), 0) as cost,
+                    IFNULL(SUM(plan_count), 0) as plan_count,
+                    IFNULL(SUM(account_count), 0) as account_count,
+                    IFNULL(SUM(agent_count), 0) as agent_count,
+                    IFNULL(SUM(register_num), 0) as register_num,
+                    ROUND(IF(SUM(register_num) > 0, SUM(cost) / SUM(register_num), 0), 2) as register_cost,
+                    IFNULL(SUM(first_role_num), 0) as first_role_num,
+                    IFNULL(SUM(new_user_total_role_num), 0) as new_user_total_role_num,
+                    ROUND(IF(SUM(first_role_num) > 0 , SUM(cost) / SUM(first_role_num), 0), 2) as first_role_cost,
+                    ROUND(IF(SUM(new_user_total_role_num) > 0 , SUM(cost) / SUM(new_user_total_role_num), 0), 2) as new_user_total_role_cost,
+                    ROUND(IF(SUM(register_num) > 0 , SUM(first_role_num) / SUM(register_num), 0), 4) as first_role_rate,
+                    ROUND(IF(SUM(register_num) > 0 , SUM(new_user_total_role_num) / SUM(register_num), 0), 4) as new_user_total_role_rate,
+                    IFNULL(SUM(first_new_user_amount_count), 0) as first_new_user_amount_count,
+                    IFNULL(SUM(first_new_user_amount_num), 0) as first_new_user_amount_num,
+                    IFNULL(SUM(first_new_user_amount), 0) as first_new_user_amount,
+                    IFNULL(SUM(new_user_total_amount_count), 0) as new_user_total_amount_count,
+                    IFNULL(SUM(new_user_total_amount_num), 0) as new_user_total_amount_num,
+                    IFNULL(SUM(new_user_total_amount), 0) as new_user_total_amount,
+                    IFNULL(SUM(buy_new_user_total_amount), 0) as buy_new_user_total_amount,
+                    IFNULL(SUM(buy_new_user_total_amount_num), 0) as buy_new_user_total_amount_num,
+                    IFNULL(SUM(buy_new_user_total_amount_count), 0) as buy_new_user_total_amount_count,
+                    ROUND(IF(SUM(cost) > 0, SUM(first_new_user_amount) / SUM(cost), 0), 4) as first_roi,
+                    ROUND(IF(SUM(cost) > 0, SUM(buy_new_user_total_amount) / SUM(cost), 0), 4) as buy_roi,
+                    ROUND(IF(SUM(cost) > 0, SUM(new_user_total_amount) / SUM(cost), 0), 4) as today_roi,
+                    IFNULL((SUM(new_user_total_amount) - SUM(cost)), 0) as gross_profit,
+                    ROUND(IF(SUM(register_num) > 0, SUM(first_new_user_amount_num) / SUM(register_num), 0), 4) as first_rate,
+                    ROUND(IF(SUM(register_num) > 0, SUM(buy_new_user_total_amount_num) / SUM(register_num), 0), 4) as buy_user_rate,
+                    ROUND(IF(SUM(register_num) > 0, SUM(new_user_total_amount_num) / SUM(register_num), 0), 4) as today_rate,
+                    ROUND(IF(SUM(first_new_user_amount_count) > 0 , SUM(first_new_user_amount) / SUM(first_new_user_amount_count), 0), 2) as first_avg,
+                    ROUND(IF(SUM(buy_new_user_total_amount_count) > 0 , SUM(buy_new_user_total_amount) / SUM(buy_new_user_total_amount_count), 0), 2) as buy_avg,
+                    ROUND(IF(SUM(new_user_total_amount_count) > 0 , SUM(new_user_total_amount) / SUM(new_user_total_amount_count), 0), 2) as today_avg,
+                    ROUND(IF(SUM(first_new_user_amount_num) > 0 , SUM(cost) / SUM(first_new_user_amount_num), 0), 2) as first_amount_cost,
+                    ROUND(IF(SUM(buy_new_user_total_amount_num) > 0 , SUM(cost) / SUM(buy_new_user_total_amount_num), 0), 2) as buy_amount_cost,
+                    ROUND(IF(SUM(new_user_total_amount_num) > 0 , SUM(cost) / SUM(new_user_total_amount_num), 0), 2) as today_amount_cost,
+                    IFNULL(SUM(reg_order_user_again), 0) as reg_order_user_again,
+                    ROUND(IF(SUM(new_user_total_amount_num) > 0 ,SUM(reg_order_user_again) / SUM(new_user_total_amount_num), 0), 4) as today_again_rate,
+                    ROUND(IF(SUM(register_num) > 0 , SUM(new_user_total_amount) / SUM(register_num), 0), 2) as new_reg_arpu,
+                    ROUND(IF(SUM(first_new_user_amount_num) > 0 , SUM(first_new_user_amount) / SUM(first_new_user_amount_num), 0), 2) as first_arpu,
+                    ROUND(IF(SUM(new_user_total_amount_num) > 0 , SUM(new_user_total_amount) / SUM(new_user_total_amount_num), 0), 2) as today_arpu,
+                    IFNULL(SUM(hundred_user_num), 0) as hundred_user_num,
+                    ROUND(IF(SUM(hundred_user_num) > 0 , SUM(cost) / SUM(hundred_user_num), 0), 2) as hundred_user_num_cost,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da1) / SUM(cost), 0), 4) as roi1,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da2) / SUM(cost), 0), 4) as roi2,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da3) / SUM(cost), 0), 4) as roi3,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da4) / SUM(cost), 0), 4) as roi4,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da5) / SUM(cost), 0), 4) as roi5,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da6) / SUM(cost), 0), 4) as roi6,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da7) / SUM(cost), 0), 4) as roi7,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da8) / SUM(cost), 0), 4) as roi8,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da9) / SUM(cost), 0), 4) as roi9,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da10) / SUM(cost), 0), 4) as roi10,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da11) / SUM(cost), 0), 4) as roi11,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da12) / SUM(cost), 0), 4) as roi12,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da13) / SUM(cost), 0), 4) as roi13,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da14) / SUM(cost), 0), 4) as roi14,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da15) / SUM(cost), 0), 4) as roi15,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da16) / SUM(cost), 0), 4) as roi16,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da17) / SUM(cost), 0), 4) as roi17,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da18) / SUM(cost), 0), 4) as roi18,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da19) / SUM(cost), 0), 4) as roi19,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da20) / SUM(cost), 0), 4) as roi20,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da21) / SUM(cost), 0), 4) as roi21,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da22) / SUM(cost), 0), 4) as roi22,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da23) / SUM(cost), 0), 4) as roi23,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da24) / SUM(cost), 0), 4) as roi24,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da25) / SUM(cost), 0), 4) as roi25,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da26) / SUM(cost), 0), 4) as roi26,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da27) / SUM(cost), 0), 4) as roi27,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da28) / SUM(cost), 0), 4) as roi28,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da29) / SUM(cost), 0), 4) as roi29,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da30) / SUM(cost), 0), 4) as roi30,
+                    ROUND(IF(SUM(cost) > 0 , SUM(m2) / SUM(cost), 0), 4) as roi60,
+                    ROUND(IF(SUM(cost) > 0 , SUM(m3) / SUM(cost), 0), 4) as roi90,
+                    ROUND(IF(SUM(cost) > 0 , SUM(m6) / SUM(cost), 0), 4) as roi180,
+                    ROUND(IF(SUM(cost) > 0 , SUM(y1) / SUM(cost), 0), 4) as roi1yaer,
+                    ROUND(IF(SUM(cost) > 0 , SUM(total) / SUM(cost), 0), 4) as roi_total
+                FROM
+                    game_ads.ads_game_pitcher_day
+                """;
+    }
+
 
 }