ソースを参照

修改内容:推广媒体每日数据、总计

lth 1 年間 前
コミット
045927e787

+ 567 - 2
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/IMediaDataServiceImpl.java

@@ -1,10 +1,32 @@
 package com.zanxiang.game.data.serve.service.impl;
 
+import com.google.common.base.CaseFormat;
 import com.zanxiang.game.data.serve.pojo.dto.*;
+import com.zanxiang.game.data.serve.pojo.entity.AdsGamePitcherAcctypeDay;
+import com.zanxiang.game.data.serve.pojo.enums.OrderByEnum;
 import com.zanxiang.game.data.serve.pojo.vo.*;
 import com.zanxiang.game.data.serve.service.IMediaDataService;
 import com.zanxiang.game.data.serve.utils.Page;
+import com.zanxiang.module.util.exception.BaseException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.nutz.dao.Cnd;
+import org.nutz.dao.Dao;
+import org.nutz.dao.Sqls;
+import org.nutz.dao.pager.Pager;
+import org.nutz.dao.sql.Criteria;
+import org.nutz.dao.sql.Sql;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import reactor.util.function.Tuple2;
+import reactor.util.function.Tuples;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author tianhua
@@ -14,6 +36,43 @@ import org.springframework.stereotype.Service;
 @Service
 public class IMediaDataServiceImpl implements IMediaDataService {
 
+    //存储PitcherGameMediaDataDayVO的映射List
+    private static final List<Tuple2<Field, Field>> pitcherGameMediaDayNMapList;
+
+    static {
+        //解析PitcherGameMediaDataDayVO的映射
+        Map<String, Field> fieldMap = new HashMap<>();
+        List<Field> dayNFieldList = new ArrayList<>();
+        Class<?> pitcherGameMediaDataDayClazz = PitcherGameMediaDataDayVO.class;
+        while (pitcherGameMediaDataDayClazz != null) {
+            Field[] fields = pitcherGameMediaDataDayClazz.getDeclaredFields();
+            for (Field field : fields) {
+                if ((Modifier.isStatic(field.getModifiers())) || Modifier.isFinal(field.getModifiers())) {
+                    continue;
+                }
+                fieldMap.put(field.getName(), field);
+                if (field.getType() == RechargeTrendVO.class) {
+                    dayNFieldList.add(field);
+                }
+            }
+            pitcherGameMediaDataDayClazz = pitcherGameMediaDataDayClazz.getSuperclass();
+        }
+        if (dayNFieldList.isEmpty()) {
+            pitcherGameMediaDayNMapList = Collections.emptyList();
+        } else {
+            pitcherGameMediaDayNMapList = new ArrayList<>(dayNFieldList.size());
+            for (Field field : dayNFieldList) {
+                field.setAccessible(true);
+                Field sourceField = fieldMap.get(field.getName().replace("Trend", ""));
+                sourceField.setAccessible(true);
+                pitcherGameMediaDayNMapList.add(Tuples.of(sourceField, field));
+            }
+        }
+    }
+
+    @Autowired
+    private Dao dao;
+
     /**
      * 推广媒体每日数据
      * @param dto PitcherGameMediaDataDayDTO
@@ -21,7 +80,61 @@ public class IMediaDataServiceImpl implements IMediaDataService {
      */
     @Override
     public Page<PitcherGameMediaDataDayVO> getPitcherGameMediaDataDay(PitcherGameMediaDataDayDTO dto) {
-        return null;
+        //创建查询条件
+        Criteria cri = Cnd.cri();
+        if (dto.getPitcherId() != null) {
+            cri.where().andEquals("pitcher_id", dto.getPitcherId());
+        }
+        if (StringUtils.isNotBlank(dto.getGameId())) {
+            cri.where().andEquals("game_id", dto.getGameId());
+        }
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            cri.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (dto.getBeginDate() != null && dto.getEndDate() != null) {
+            cri.where().andBetween("dt", dto.getBeginDate(), dto.getEndDate());
+        }
+        if (StringUtils.isNotBlank(dto.getGameCp())) {
+            cri.where().andEquals("game_cp", dto.getGameCp());
+        }
+        if (dto.getGameType() != null) {
+            cri.where().andEquals("game_type", dto.getGameType());
+        }
+        if (StringUtils.isNotBlank(dto.getAccountType())) {
+            cri.where().andEquals("account_type", dto.getAccountType());
+        }
+        //排序条件
+        //拼接排序条件,如果没有排序条件给默认值
+        if (StringUtils.isBlank(dto.getSortType())) {
+            dto.setSortType(OrderByEnum.DESC.getOrderType());
+        }
+        if (StringUtils.isBlank(dto.getSortFiled())) {
+            cri.getOrderBy().orderBy("dt", dto.getSortType());
+            cri.getOrderBy().orderBy("cost", dto.getSortType());
+        } else {
+            cri.getOrderBy().orderBy(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dto.getSortFiled()), dto.getSortType());
+        }
+        //Pager对象
+        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
+        //sql语句
+        Sql sql = Sqls.create(pitcherGameMediaDataDaySql() + cri);
+        //设置回传对象
+        sql.setCallback(Sqls.callback.entities());
+        sql.setEntity(dao.getEntity(PitcherGameMediaDataDayVO.class));
+        //设置pager
+        sql.setPager(pager);
+        //执行sql
+        dao.execute(sql);
+        //设置总记录数
+        pager.setRecordCount(dao.count(AdsGamePitcherAcctypeDay.class, cri));
+        //处理dayN数据
+        List<PitcherGameMediaDataDayVO> tempList = sql.getList(PitcherGameMediaDataDayVO.class);
+        List<PitcherGameMediaDataDayVO> list = tempList.stream().map(vo -> {
+            formatPitcherGameMediaDataDayDayN(vo);
+            return vo;
+        }).collect(Collectors.toList());
+        //返回结果
+        return new Page<>(list, pager);
     }
 
     /**
@@ -31,7 +144,42 @@ public class IMediaDataServiceImpl implements IMediaDataService {
      */
     @Override
     public PitcherGameMediaDataDayVO getPitcherGameMediaDataDayTotal(PitcherGameMediaDataDayTotalDTO dto) {
-        return null;
+        //创建查询条件
+        Criteria cri = Cnd.cri();
+        if (dto.getPitcherId() != null) {
+            cri.where().andEquals("pitcher_id", dto.getPitcherId());
+        }
+        if (StringUtils.isNotBlank(dto.getGameId())) {
+            cri.where().andEquals("game_id", dto.getGameId());
+        }
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            cri.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (dto.getBeginDate() != null && dto.getEndDate() != null) {
+            cri.where().andBetween("dt", dto.getBeginDate(), dto.getEndDate());
+        }
+        if (StringUtils.isNotBlank(dto.getGameCp())) {
+            cri.where().andEquals("game_cp", dto.getGameCp());
+        }
+        if (dto.getGameType() != null) {
+            cri.where().andEquals("game_type", dto.getGameType());
+        }
+        if (StringUtils.isNotBlank(dto.getAccountType())) {
+            cri.where().andEquals("account_type", dto.getAccountType());
+        }
+        //sql语句
+        Sql sql = Sqls.create(pitcherGameMediaDataDayTotalSql() + cri);
+        //设置回传对象
+        sql.setCallback(Sqls.callback.entity());
+        sql.setEntity(dao.getEntity(PitcherGameMediaDataDayVO.class));
+        //执行sql
+        dao.execute(sql);
+        PitcherGameMediaDataDayVO vo = sql.getObject(PitcherGameMediaDataDayVO.class);
+        if (StringUtils.isNotBlank(vo.getAmountD1())) {
+            //处理dayN数据
+            formatPitcherGameMediaDataDayTotalDayN(vo);
+        }
+        return vo;
     }
 
     /**
@@ -133,4 +281,421 @@ public class IMediaDataServiceImpl implements IMediaDataService {
     public GameMediaDataTotalVO getGameMediaDataTotalSum(GameMediaDataTotalSumDTO dto) {
         return null;
     }
+
+    /**
+     * 处理推广媒体每日数据的DayN数据
+     * @param vo PitcherGameMediaDataDayVO
+     */
+    private void formatPitcherGameMediaDataDayDayN(PitcherGameMediaDataDayVO vo) {
+        if (CollectionUtils.isEmpty(pitcherGameMediaDayNMapList)) {
+            return;
+        }
+        pitcherGameMediaDayNMapList.forEach(dayNFieldMap -> {
+            try {
+                String[] temps = ((String) dayNFieldMap.getT1().get(vo)).split("/");
+                dayNFieldMap.getT2().set(vo, RechargeTrendVO.builder()
+                        .rechargeMoney(new BigDecimal(temps[0]))
+                        .rechargeUserCount(Long.valueOf(temps[1]))
+                        .increase(new BigDecimal(temps[2]))
+                        .back(new BigDecimal(temps[3]))
+                        .multiples(new BigDecimal(temps[4]))
+                        .build());
+            } catch (Exception e) {
+                throw new BaseException("映射出错");
+            }
+        });
+    }
+
+    /**
+     * 处理投手游戏每日总计的DayN(投手游戏每日总计)
+     *
+     * @param vo PitcherGameDataDayTotalVO
+     */
+    private void formatPitcherGameMediaDataDayTotalDayN(PitcherGameMediaDataDayVO vo) {
+        if (CollectionUtils.isEmpty(pitcherGameMediaDayNMapList)) {
+            return;
+        }
+        pitcherGameMediaDayNMapList.forEach(dayNTotalFieldMap -> {
+            try {
+                //得到需要计算的值
+                String[] temps = ((String) dayNTotalFieldMap.getT1().get(vo)).split("/");
+                //dn的金额总计
+                BigDecimal dNAmount = new BigDecimal(temps[0]);
+                //d1-dn的金额总计
+                BigDecimal d1ToDNTotalAmount = new BigDecimal(temps[1]);
+                //d1-dn的消耗总计(排除了未到时间的cost)
+                BigDecimal d1ToDNTotalCost = new BigDecimal(temps[3]);
+                //d1的金额总计(排除了未到时间的d1)
+                BigDecimal d1Amount = new BigDecimal(temps[4]);
+                //赋值
+                dayNTotalFieldMap.getT2().set(vo, RechargeTrendVO.builder()
+                        .rechargeMoney(dNAmount)
+                        .rechargeUserCount(Long.valueOf(temps[2]))
+                        .increase(d1ToDNTotalCost.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
+                                dNAmount.divide(d1ToDNTotalCost, 4, RoundingMode.HALF_UP))
+                        .back(d1ToDNTotalCost.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
+                                d1ToDNTotalAmount.divide(d1ToDNTotalCost, 4, RoundingMode.HALF_UP))
+                        .multiples(d1Amount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO :
+                                d1ToDNTotalAmount.divide(d1Amount, 4, RoundingMode.HALF_UP))
+                        .build());
+            } catch (Exception e) {
+                throw new BaseException("映射出错");
+            }
+        });
+    }
+
+    /**
+     * 推广媒体每日数据SQL
+     * @return String
+     */
+    private String pitcherGameMediaDataDaySql() {
+        return """
+                SELECT
+                    dt,
+                    source_system,
+                    pitcher_id,
+                    game_id,
+                    pitcher,
+                    game_name,
+                    game_cp,
+                    game_type,
+                    account_type,
+                    cost,
+                    plan_count,
+                    account_count,
+                    agent_count,
+                    register_num,
+                    first_new_user_amount_count,
+                    first_new_user_amount_num,
+                    first_new_user_amount,
+                    amount_count,
+                    amount_num,
+                    amount,
+                    old_amount_count,
+                    old_amount_num,
+                    old_amount,
+                    new_user_total_amount_count,
+                    new_user_total_amount_num,
+                    new_user_total_amount,
+                    hundred_user_num,
+                    buy_new_user_total_amount,
+                    buy_new_user_total_amount_num,
+                    buy_new_user_total_amount_count,
+                    reg_order_user_again,
+                    first_role_num,
+                    new_user_total_role_num,
+                    role_num,
+                    register_cost,
+                    first_roi,
+                    buy_roi,
+                    today_roi,
+                    gross_profit,
+                    first_rate,
+                    buy_user_rate,
+                    today_rate,
+                    first_avg,
+                    buy_avg,
+                    today_avg,
+                    paper_avg,
+                    first_amount_cost,
+                    buy_amount_cost,
+                    today_amount_cost,
+                    today_again_rate,
+                    new_reg_arpu,
+                    first_arpu,
+                    today_arpu,
+                    paper_arpu,
+                    hundred_user_num_cost,
+                    roi1,
+                    roi2,
+                    roi3,
+                    roi4,
+                    roi5,
+                    roi6,
+                    roi7,
+                    roi8,
+                    roi9,
+                    roi10,
+                    roi11,
+                    roi12,
+                    roi13,
+                    roi14,
+                    roi15,
+                    roi16,
+                    roi17,
+                    roi18,
+                    roi19,
+                    roi20,
+                    roi21,
+                    roi22,
+                    roi23,
+                    roi24,
+                    roi25,
+                    roi26,
+                    roi27,
+                    roi28,
+                    roi29,
+                    roi30,
+                    roi60,
+                    roi90,
+                    roi180,
+                    roi1yaer,
+                    roi_total,
+                    amount_d1,
+                    amount_d2,
+                    amount_d3,
+                    amount_d4,
+                    amount_d5,
+                    amount_d6,
+                    amount_d7,
+                    amount_d8,
+                    amount_d9,
+                    amount_d10,
+                    amount_d11,
+                    amount_d12,
+                    amount_d13,
+                    amount_d14,
+                    amount_d15,
+                    amount_d16,
+                    amount_d17,
+                    amount_d18,
+                    amount_d19,
+                    amount_d20,
+                    amount_d21,
+                    amount_d22,
+                    amount_d23,
+                    amount_d24,
+                    amount_d25,
+                    amount_d26,
+                    amount_d27,
+                    amount_d28,
+                    amount_d29,
+                    amount_d30,
+                    amount_d31,
+                    amount_d32,
+                    amount_d33,
+                    amount_d34,
+                    amount_d35,
+                    amount_d36,
+                    amount_d37,
+                    amount_d38,
+                    amount_d39,
+                    amount_d40,
+                    amount_d41,
+                    amount_d42,
+                    amount_d43,
+                    amount_d44,
+                    amount_d45,
+                    amount_d46,
+                    amount_d47,
+                    amount_d48,
+                    amount_d49,
+                    amount_d50,
+                    amount_d51,
+                    amount_d52,
+                    amount_d53,
+                    amount_d54,
+                    amount_d55,
+                    amount_d56,
+                    amount_d57,
+                    amount_d58,
+                    amount_d59,
+                    amount_d60,
+                    amount_d61,
+                    amount_d62,
+                    amount_d63,
+                    amount_d64,
+                    amount_d65,
+                    amount_d66,
+                    amount_d67,
+                    amount_d68,
+                    amount_d69,
+                    amount_d70,
+                    amount_d71,
+                    amount_d72,
+                    amount_d73,
+                    amount_d74,
+                    amount_d75,
+                    amount_d76,
+                    amount_d77,
+                    amount_d78,
+                    amount_d79,
+                    amount_d80,
+                    amount_d81,
+                    amount_d82,
+                    amount_d83,
+                    amount_d84,
+                    amount_d85,
+                    amount_d86,
+                    amount_d87,
+                    amount_d88,
+                    amount_d89,
+                    amount_d90,
+                    amount_m4,
+                    amount_m5,
+                    amount_m6,
+                    amount_m7,
+                    amount_m8,
+                    amount_m9,
+                    amount_m10,
+                    amount_m11,
+                    amount_m12,
+                    amount_sum,
+                    first_role_cost,
+                    new_user_total_role_cost,
+                    role_num_cost,
+                    first_role_rate,
+                    new_user_total_role_rate,
+                    role_num_rate,
+                    new_user_amount_ratio
+                FROM
+                    game_ads.ads_game_pitcher_acctype_day
+                """;
+
+    }
+
+    /**
+     * 推广媒体每日数据总计SQL
+     * @return String
+     */
+    private String pitcherGameMediaDataDayTotalSql() {
+        return """
+                SELECT
+                    SUM(cost) as cost,
+                    SUM(plan_count) as plan_count,
+                    SUM(account_count) as account_count,
+                    SUM(agent_count) as agent_count,
+                    SUM(register_num) as register_num,
+                    ROUND(IF(SUM(register_num) > 0, SUM(cost) / SUM(register_num), 0), 2) as register_cost,
+                    SUM(first_role_num) as first_role_num,
+                    SUM(new_user_total_role_num) as new_user_total_role_num,
+                    SUM(role_num) as role_num,
+                    ROUND(IF(SUM(role_num) > 0 , SUM(cost) / SUM(role_num), 0), 2) as role_num_cost,
+                    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,
+                    ROUND(IF(SUM(register_num) > 0 , SUM(role_num) / SUM(register_num), 0), 4) as role_num_rate,
+                    SUM(first_new_user_amount_count) as first_new_user_amount_count,
+                    SUM(first_new_user_amount_num) as first_new_user_amount_num,
+                    SUM(first_new_user_amount) as first_new_user_amount,
+                    SUM(amount_count) as amount_count,
+                    SUM(amount_num) as amount_num,
+                    SUM(amount) as amount,
+                    SUM(old_amount_count) as old_amount_count,
+                    SUM(old_amount_num) as old_amount_num,
+                    SUM(old_amount) as old_amount,
+                    SUM(new_user_total_amount_count) as new_user_total_amount_count,
+                    SUM(new_user_total_amount_num) as new_user_total_amount_num,
+                    SUM(new_user_total_amount) as new_user_total_amount,
+                    SUM(buy_new_user_total_amount) as buy_new_user_total_amount,
+                    SUM(buy_new_user_total_amount_num) as buy_new_user_total_amount_num,
+                    SUM(buy_new_user_total_amount_count) 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,
+                    (SUM(new_user_total_amount) - SUM(cost)) 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(amount_num) > 0, SUM(first_new_user_amount_num) / SUM(amount_num), 0), 4) as new_user_amount_ratio,
+                    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(amount_count) > 0 , SUM(amount) / SUM(amount_count), 0), 2) as paper_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,
+                    SUM(reg_order_user_again) 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,
+                    ROUND(IF(SUM(amount_num) > 0 , SUM(amount) / SUM(amount_num), 0), 2) as paper_arpu,
+                    SUM(hundred_user_num) 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(da60) / SUM(cost), 0), 4) as roi60,
+                    ROUND(IF(SUM(cost) > 0 , SUM(da90) / 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(m12) / SUM(cost), 0), 4) as roi1yaer,
+                    ROUND(IF(SUM(cost) > 0 , SUM(total) / SUM(cost), 0), 4) as roi_total,
+                """ + getMeidaDataDayTotalDayNsql() +
+                """
+                FROM
+                    game_ads.ads_game_pitcher_acctype_day
+                """;
+    }
+
+    /**
+     * 媒体相关的每日数据总计付费趋势SQL(推广媒体每日总计、投手媒体每日总计、游戏媒体每日总计)
+     * @return String : Dn的充值金额 / D1-Dn的充值总金额 / Dn的充值人数 /当前消耗(剔除不存在的天数数据) /D1充值金额总和(剔除不存在的天数数据)
+     */
+    private String getMeidaDataDayTotalDayNsql() {
+        StringBuilder totalDayN = new StringBuilder(StringUtils.EMPTY);
+        for (int day = 1; day <= 90 ; day++) {
+            totalDayN.append("""
+                    CONCAT(
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s day) <= LocalDate.now(), SPLIT_PART(amount_d%s , '/', 1), 0)),'/',
+                        SUM(SPLIT_PART(amount_d%s, '/', 6)),'/',
+                        SUM(SPLIT_PART(amount_d%s, '/', 2)),'/',
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s day) <= LocalDate.now(), cost, 0)),'/',
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s day) <= LocalDate.now(), SPLIT_PART(amount_d1 , '/', 1), 0))
+                    ) AS amount_d%s ,
+                       """.formatted(day - 1, day, day, day, day - 1, day - 1, day));
+        }
+        for (int month = 4; month <= 12 ; month ++) {
+            totalDayN.append("""
+                    CONCAT(
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s month) <= LocalDate.now(), SPLIT_PART(amount_m%s , '/', 1), 0)),'/',
+                        SUM(SPLIT_PART(amount_m%s, '/', 6)),'/',
+                        SUM(SPLIT_PART(amount_m%s, '/', 2)),'/',
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s month) <= LocalDate.now(), cost, 0)),'/',
+                        SUM(IF(DATE_ADD(dt, INTERVAL %s month) <= LocalDate.now(), SPLIT_PART(amount_d1 , '/', 1), 0))
+                    ) AS amount_m%s ,
+                       """.formatted(month, month, month, month, month, month, month));
+        }
+        totalDayN.append("""
+                CONCAT(
+                    SUM(SPLIT_PART(amount_sum, '/', 1)), '/',
+                    SUM(SPLIT_PART(amount_sum, '/', 6)), '/',
+                    SUM(SPLIT_PART(amount_sum, '/', 2)), '/',
+                    SUM(cost), '/',
+                    SUM(SPLIT_PART(amount_d1 , '/', 1))
+                    ) AS amount_sum
+                """);
+        //返回结果
+        return totalDayN.toString();
+    }
+
+
 }