Mysql--报表业务处理

一. 背景

在日常工作中,我们可能会经常遇到一些业务报表数据的处理。比如,在电商业务里,我们可以通过报表清晰地了解每日销售总额,订单数量以及平均订单金额等关键指标。我们在报名参加训练营挑战时,也会有各种类型数据的统计。那我们该如何处理这种类型的业务呢?



这里我们以不同类型的训练营参加人数,训练营的挑战情况报表作为这次案例分析的主体。

二. 报表业务处理

2.1 业务说明

我们先来看一下目前训练营表,用户与训练营的关联表的基本表设计

训练营表

用户与训练营关联表


结合图表信息,我们不难看出第一个环形图是以训练营的业务类型进行分组归档。我们可以结合train_camp_type 进行分组即可得到对应的数据结果。

而第二个环形图中,有开启/未开启维度 ,也有挑战成功,失败,进行中维度。其中表设计上有一个很大的弊端,就是没有维护挑战失败的数据。我们只能通过sql 条件判断的维度进行查询。

2.2 sql 实现查询

训练营类型分组

sql 复制代码
SELECT
   tc.`train_camp_type` AS trainCampType,
   COUNT(1) AS trainCampCount
   FROM mkt.train_camp_user tcu
WHERE tcu.is_allow = 1
GROUP BY tc.`train_camp_type`

在表查出分组数据后,再通过代码对信息进行赋值

闯关情况类型分组

不同于第一个环形图,这里的闯关情况可以说是两个不同的维度。一个维度是未开启和已开启的分组,一个维度是挑战中,挑战成功,挑战失败的分组。对于第一个维度相对来说比较简单;而第二个维度中挑战失败的数据是只能通过 sql 条件进行拆解;

sql 复制代码
<!--挑战情况查询-->
<if test="query.isSuccess !=null and '' != query.isSuccess">
    <choose>
        <when test="query.isSuccess == 2">
            AND tcu.`is_open` =1 AND tcu.is_success = 0 AND NOW() >= tcu.train_camp_end_time
        </when>
        <when test="query.isSuccess == 0">
            AND tcu.`is_open` =1 AND tcu.is_success = 0 AND NOW()  <![CDATA[ < ]]>  tcu.train_camp_end_time
        </when>
        <otherwise>
             AND tcu.`is_open` =1 AND tcu.is_success = #{query.isSuccess}
        </otherwise>
    </choose>
</if>

对于上面的sql 也能很好的完成业务,不过需要每个挑战情况传入对应的值进行查询;相对来说加大了对数据库多次连接操作的压力。

而我们如果转换一种思路,把对应的条件写成对应的查询列中,不仅可以解决第二种维度的分组,甚至可以巧妙地把未开启的数据也进行归类,因为挑战中,挑战成功,挑战失败的训练营必须是已开启状态的。我们可以通过以下分段查询出对应挑战情况的数据。

sql 复制代码
SELECT
    challenge_status,
    COUNT(*) AS status_count
FROM (
    -- 子查询,用于根据条件生成不同挑战状态的新列
    SELECT tcu.id,
           CASE
               -- 挑战失败情况(对应query.isSuccess == 2的情况)
               WHEN tcu.`is_open` =1 AND  tcu.is_success = 0 AND NOW() > tcu.train_camp_end_time THEN '失败'
               -- 挑战进行中情况(对应query.isSuccess == 0的情况)
               WHEN tcu.`is_open` =1 AND tcu.is_success = 0 AND NOW() <= tcu.train_camp_end_time THEN '进行中'
               -- 挑战成功情况(其他情况,即query.isSuccess为1或者其他表示成功的值)
               WHEN tcu.`is_open` =1 AND tcu.is_success = 1 THEN '成功'
               ELSE '未开启'
               END AS challenge_status
    FROM train_camp_user tcu
    LEFT JOIN mkt.train_camp tc ON tc.id = tcu.train_camp_id
    WHERE tcu.`is_allow` = 1
) AS subquery
GROUP BY challenge_status;
相关推荐
gadiaola2 分钟前
【JavaSE面试篇】Java集合部分高频八股汇总
java·面试
GJCTYU14 分钟前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
艾迪的技术之路24 分钟前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗98042 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师1 小时前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
咖啡啡不加糖1 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南1 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
DKPT1 小时前
Java享元模式实现方式与应用场景分析
java·笔记·学习·设计模式·享元模式