产品需求:

1、日报表

2、月报表

需求点: 前端传日期或月份区间,当数据库中指定的日期或月份没数据时也需要界面显示,但领取人数和使用人数需要自动补齐0;
举例:2020-11-28、2020-11-29,数据库中没数据,但也需要在界面显示,领取人数和使用人数为0;

思路很重要

1、首先根据前端传来的时间区间,查询出区间中所有的日期或月份;
2、然后循环日期或月份和数据库查询返回的List<实体对象>的日期或月份进行匹配;
2.1、不存在则在List<实体对象>中新增一条实体对象数据;
3、最后统一把处理后的List<实体对象>返回前端;

sql语句(后面Mapper.xml中全部详细列出)

注:这里是Mysql数据库,以日报表为例,** 月报表则是将 DATE_FORMAT格式修改为 %Y-%m 即可 **

<!-- 根据日期分组查询 “领取人数” 和 “使用人数”,然后将两个Sql查询结果汇总 -->SELECTt.days,sum( t.receiveQty ) AS receiveQty,sum( t.userQty ) AS userQty
FROM(<!-- 领取人数 -->SELECTDATE_FORMAT( r.created_time, '%Y-%m-%d' ) AS days,count( r.id ) AS receiveQty,0 AS userQty FROMdg_experience_receive rLEFT JOIN dg_experience_order o ON r.user_id = o.user_id WHEREDATE_FORMAT( r.created_time, '%Y-%m-%d' ) >= '2020-11-01' AND DATE_FORMAT( r.created_time, '%Y-%m-%d' ) <= '2020-12-16' GROUP BYdays UNION ALL<!-- 使用人数 -->SELECTDATE_FORMAT( r.created_time, '%Y-%m-%d' ) AS days,0 AS receiveQty,count( r.id ) AS userQty FROMdg_experience_receive rJOIN dg_experience_order o ON r.user_id = o.user_id WHEREr.is_used = 1 AND DATE_FORMAT( r.created_time, '%Y-%m-%d' ) >= '2020-11-01' AND DATE_FORMAT( r.created_time, '%Y-%m-%d' ) <= '2020-12-16' GROUP BYdays ) t
GROUP BYdays
ORDER BYdays DESC;

请求实体

@Data
public class DepositExperienceDayReq {/*** 开始日期*/@NotBlank(message = "起始日期不能为空!")private String startDate;/*** 结束日期*/@NotBlank(message = "截至日期不能为空!")private String endDate;
}

返回实体

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DepositExperienceDayRes {/*** 日期*/private String days;/*** 领取人数*/private Long receiveQty;/*** 使用人数*/private Long userQty;
}

Controller

/*** 体验金日报表--查询*/@PostMapping("/experienceDay/list")public ResponseData listExperienceDayByReq(@Valid @RequestBody DepositExperienceDayReq experienceDayReq){return ResponseData.success(experienceOrderService.listExperienceDayByReq(experienceDayReq));}/*** 体验金月报表--查询*/@PostMapping("/experienceMonth/list")public ResponseData listExperienceMonthByReq(@Valid @RequestBody DepositExperienceDayReq experienceDayReq){return ResponseData.success(experienceOrderService.listExperienceMonthByReq(experienceDayReq));}

Service

/*** 运营报表--体验金日报表--查询* @param experienceDayReq* @return*/List<DepositExperienceDayRes> listExperienceDayByReq(DepositExperienceDayReq experienceDayReq);/*** 运营报表--体验金月报表--查询* @param experienceDayReq* @return*/List<DepositExperienceDayRes> listExperienceMonthByReq(DepositExperienceDayReq experienceDayReq);

ServiceImpl(这里是重点,需要看一下)

注: DateUtil使用的是 hutool-core-5.0.6.jar

    /*** 运营报表--体验金日报表--查询* @param experienceDayReq* @return*/@Overridepublic List<DepositExperienceDayRes> listExperienceDayByReq(DepositExperienceDayReq experienceDayReq) {// 首先根据前端传来的时间区间,查询出区间中所有的日期;List<Date> lDate = findDates(DateUtil.parseDate(experienceDayReq.getStartDate()), DateUtil.parseDate(experienceDayReq.getEndDate()), Calendar.DAY_OF_MONTH);if (CollectionUtils.isEmpty(lDate)){return null;}List<DepositExperienceDayRes> experienceDayResList = baseMapper.listExperienceDayByReq(experienceDayReq);for (Date date : lDate){// 当前日期不存在则新增String dateStr = DateUtil.format(date, "yyyy-MM-dd");// 进行匹配if(!experienceDayResList.stream().filter(item -> dateStr.equals(item.getDays())).findAny().isPresent()){DepositExperienceDayRes experienceDayRes = DepositExperienceDayRes.builder().days(dateStr).receiveQty(0L).userQty(0L).build();experienceDayResList.add(experienceDayRes);}}List<DepositExperienceDayRes> collect = experienceDayResList.stream().sorted(Comparator.comparing(DepositExperienceDayRes::getDays).reversed()).collect(Collectors.toList());return collect;}/*** 运营报表--体验金月报表--查询* @param experienceDayReq* @return*/@Overridepublic List<DepositExperienceDayRes> listExperienceMonthByReq(DepositExperienceDayReq experienceDayReq) {// 首先根据前端传来的时间区间,查询出区间中所有的月份;DateTime startDate = DateUtil.parse(experienceDayReq.getStartDate(), "yyyy-MM");DateTime endDate = DateUtil.parse(experienceDayReq.getEndDate(), "yyyy-MM");List<Date> lDate = findDates(startDate, endDate, Calendar.MONTH);if (CollectionUtils.isEmpty(lDate)){return null;}List<DepositExperienceDayRes> experienceDayResList = baseMapper.listExperienceMonthByReq(experienceDayReq);for (Date date : lDate){// 当前日期不存在则新增String dateStr = DateUtil.format(date, "yyyy-MM");// 进行匹配if(!experienceDayResList.stream().filter(item -> dateStr.equals(item.getDays())).findAny().isPresent()){DepositExperienceDayRes experienceDayRes = DepositExperienceDayRes.builder().days(dateStr).receiveQty(0L).userQty(0L).build();experienceDayResList.add(experienceDayRes);}}List<DepositExperienceDayRes> collect = experienceDayResList.stream().sorted(Comparator.comparing(DepositExperienceDayRes::getDays).reversed()).collect(Collectors.toList());return collect;}/*** 获取指定时间区间的所有数据(包含日期和月份)* @param dBegin* @param dEnd* @param rule 日历规则 如:Calendar.DAY_OF_MONTH* @return*/public static List<Date> findDates(Date dBegin, Date dEnd, int rule) {List lDate = new ArrayList();if (dEnd.before(dBegin)){return lDate;}lDate.add(dBegin);Calendar calBegin = Calendar.getInstance();// 使用给定的 Date 设置此 Calendar 的时间calBegin.setTime(dBegin);Calendar calEnd = Calendar.getInstance();// 使用给定的 Date 设置此 Calendar 的时间calEnd.setTime(dEnd);// 测试此日期是否在指定日期之后while (dEnd.after(calBegin.getTime())) {// 根据日历的规则,为给定的日历字段添加或减去指定的时间量calBegin.add(rule, 1);lDate.add(calBegin.getTime());}return lDate;}

Mapper.xml

 <!-- 日报表 -->
<select id="listExperienceDayByReq"resultType="com.dg.mall.financial.vo.res.report.operation.DepositExperienceDayRes">SELECTt.days,sum(t.receiveQty) as receiveQty,sum(t.userQty) as userQtyFROM (SELECTDATE_FORMAT(r.created_time , '%Y-%m-%d' ) AS days,count(r.id) as receiveQty,0 as userQtyFROM dg_experience_receive rLEFT JOIN dg_experience_order o on r.user_id = o.user_id<where><if test="experienceDayReq.startDate != null and experienceDayReq.startDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m-%d') >= #{experienceDayReq.startDate} ]]></if><if test="experienceDayReq.endDate != null and experienceDayReq.endDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m-%d') <= #{experienceDayReq.endDate} ]]></if></where>GROUP BY daysUNION ALLSELECTDATE_FORMAT(r.created_time , '%Y-%m-%d' ) AS days,0 as receiveQty,count(r.id) as userQtyFROM dg_experience_receive rJOIN dg_experience_order o on r.user_id = o.user_id<where>AND r.is_used = 1<if test="experienceDayReq.startDate != null and experienceDayReq.startDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m-%d') >= #{experienceDayReq.startDate} ]]></if><if test="experienceDayReq.endDate != null and experienceDayReq.endDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m-%d') <= #{experienceDayReq.endDate} ]]></if></where>GROUP BY days) tGROUP BY daysorder by days desc</select><!-- 月报表 --><select id="listExperienceMonthByReq"resultType="com.dg.mall.financial.vo.res.report.operation.DepositExperienceDayRes">SELECTt.days,sum(t.receiveQty) as receiveQty,sum(t.userQty) as userQtyFROM (SELECTDATE_FORMAT(r.created_time , '%Y-%m' ) AS days,count(r.id) as receiveQty,0 as userQtyFROM dg_experience_receive rLEFT JOIN dg_experience_order o on r.user_id = o.user_id<where><if test="experienceDayReq.startDate != null and experienceDayReq.startDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m') >= #{experienceDayReq.startDate} ]]></if><if test="experienceDayReq.endDate != null and experienceDayReq.endDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m') <= #{experienceDayReq.endDate} ]]></if></where>GROUP BY daysUNION ALLSELECTDATE_FORMAT(r.created_time , '%Y-%m' ) AS days,0 as receiveQty,count(r.id) as userQtyFROM dg_experience_receive rJOIN dg_experience_order o on r.user_id = o.user_id<where>AND r.is_used = 1<if test="experienceDayReq.startDate != null and experienceDayReq.startDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m') >= #{experienceDayReq.startDate} ]]></if><if test="experienceDayReq.endDate != null and experienceDayReq.endDate != ''"><![CDATA[ AND DATE_FORMAT(r.created_time, '%Y-%m') <= #{experienceDayReq.endDate} ]]></if></where>GROUP BY days) tGROUP BY daysorder by days desc</select>

PostMan结果展示:



之前是将该文章放在简书中,后面发现简书的页面编辑功能没有这里多,今天就把它移过来了。

下一篇将会记录使用:Elasticsearch(简称ES)实现日报表、月报表、年报表统计,没数据补0功能
https://blog.csdn.net/JRocks/article/details/113842092

java实现日报表、月报表统计,没数据补0相关推荐

  1. es统计mysql 报表_Elasticsearch(简称ES)实现日报表、月报表、年报表统计,没数据补0...

    前言: 这是1张相对简单些报表示例,用sql语句也能实现,但主要是为了便于大家理解ES聚合实现报表的使用方法. 之前写过"java实现日报表.月报表统计,没数据补0"文章,http ...

  2. Elasticsearch(简称ES)实现日报表、月报表、年报表统计,没数据补0

    前言: 这是1张相对简单些报表示例,用sql语句也能实现,但主要是为了便于大家理解ES聚合实现报表的使用方法. 之前写过"java实现日报表.月报表统计,没数据补0"文章,http ...

  3. mysql分季度统计数据,mysql按日周月季度统计数据

    mysql按日周月季度统计数据 mysql按日.周.月.季度统计数据 1.使用DATE_FORMAT做等值条件查询 2.DATE_FORMAT函数语法,参考w3school 3.可使用格式 4.使用示 ...

  4. wincc报表 日报表 月报表 年报表 时段报表:可自由选择时间段查询

    wincc报表 功能如下: 日报表:每日24点数据,如果设置的是累计值,计算每小时的差值,和最终汇总一日总累计 月报表:每日0点数据显示,如果设置的是累计值,计算每日的差值,和最终汇总一月总累计 年报 ...

  5. wincc报表 日报表 月报表 年报表 时段报表 报表表格 宽度可以自由配置,报表界面大小可以自由拖动大小,报表参数方便配置,不需要任何编程,适用wincc任何版本

    wincc报表 功能如下: 日报表:每日24点数据,如果设置的是累计值,计算每小时的差值,和最终汇总一日总累计 月报表:每日0点数据显示,如果设置的是累计值,计算每日的差值,和最终汇总一月总累计 年报 ...

  6. Oracle按日周月分组统计,及next_day()函数详解

    1.概述 工作中遇到如下问题:统计周期内关键词数,而这里的周期内最常用的就是日周月. 日月比较容易处理,周的话可以通过next_day()函数实现. 2.实例问题 如下,有一张表ljb_test,包括 ...

  7. sqlserver查询补全时间_mssql 按日期分组(group by)查询统计的时候,没有数据补0的解决办法...

    摘要: 下文讲述一次报表制作的需求, 需制作一个月的销量的数据汇总,如果其中某一天没有数据,那么就补0处理 例: /* 统计2018-4月份的销量统计, 无数据的天补0 */ ---建立基础数据 cr ...

  8. MySQL按天统计一周没有数据补0

    背景:统计图表所需数据,当天没有数据时需要补0 思路:关联查询(所需时间列表与统计结果) 步骤: 第一步:获取一周的日期列表 SELECT @cdate := DATE_ADD(@cdate, INT ...

  9. sql 没数据补零_SQL 小白入门小课堂

    引子 我老婆前阵子被老板安排了一个运营项目,需要写 SQL 分析数据.对于对 SQL 一窍不通.甚至从没接触过代码的我老婆来说,简直抓瞎. 鉴于我是前端工程师,搞全栈的时候也写过不少 SQL,刚好可以 ...

最新文章

  1. ECCV 2020 | PHOSA:一种基于单目图像的人-物重建方法
  2. 有人说 GPT3 是“暴力美学”的结晶,它的工作原理你知道吗?| 动图详解
  3. 插件和代码两种方法搞定WordPress回复邮件通知
  4. typedef 的四个用途和两大陷阱
  5. 迭代器 java_Java设计模式8:迭代器模式
  6. 在单用户模式下启动SQL Server的不同方法
  7. 深度学习和拓扑数据分析的六大惊人之举
  8. 微信JS SDK网页接口
  9. Apache Pulsar 中文社区先锋奖与年度优秀案例出炉!
  10. 小白的破解WiFi之路1----VMware、kali安装
  11. ArcGIS API for JavaScript开发之必学渲染方式及渲染符号概念(0)
  12. zmq pub/sub使用详解
  13. CSS3的癫疯展示——3D立方体动画(你要的全景视图来了)
  14. IDM6.32的安装与激活IDM Crack 6.32 Build 8 + Patch 2019 free (100% working)
  15. andriod手机信号显示G、E、H、T是什么意思?
  16. QSFP28 LR4单模光模块与其它100G光模块有什么区别
  17. matlab中度数化成度分秒,地学中常用度、度分、度分秒,弧度、角度在MATLAB中的转换...
  18. 山东云则-您身边的物联网专家,助您快速接入物联网
  19. 反燃油车占位方案:AI识别+EasyCVR解决燃油车占位问题
  20. c++成员函数指针揭秘

热门文章

  1. python整钱换零钱_一知半解讲Python第二季:7.钞票兑换
  2. Tessellation Shader(细分曲面着色器)
  3. 抄都抄的不认真,水印都没抹掉!小红书怒斥大众点评
  4. python登录网站后爬取数据_快速爬取登录网站数据
  5. Photoshop中文版免费在线网站哪个好
  6. java输入坐标_用java语言编写输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离....
  7. 通达信众赢全部指标(源码副图)
  8. 应用程序及进程守护天使---web服务器看门狗程序
  9. 一个研究生读完三年需要花多少钱?
  10. ISNULL和NULLIF函数