关于如何获取上周均值的实时数据思路,吾之解合君意否?

    📚 在前端界面图形化展示中,目前主流以报表形式,或者以曲线图形式展示其所需数据的数字动态变化效果居多。在数据量不大或者不需要模糊对比的情况下,我们以报表展示为主;而我们需要从肉眼宏观可见的监控数据变化,一眼能看出其数据变动问题的时候,曲线图的展示则是首选。

    📕 刚开始接手做项目大家应该都是从报表入手,因为这个较为简单,容易上手,逻辑上判断也并不复杂。但是曲线图上的开发考虑的因素就要更多一些:
⛳️(1)曲线数据值的取法怎样合适?
⛳️(2)曲线坐标轴当以多少分钟为时间间隔合适?
⛳️(3)数据库数据是否在所统计的时间点上有数值
⛳️(4)没有数值应当以何种方式进行补值

    ✂️这些并不是本人一开始就得知的,而是踩过坑并和前端同事对接后发现的问题。所谓不在其位不谋其政,一旦在岗工作有些坑该踩还得踩,该流的汗还得流,当然遇到很不合理的需求该battle还得battle~
    ✂️习惯上先说一段废话来引入主题:聊聊是如何获取上周均值的实时数据的(曲线图),主要根据曲线要考虑的因素展开思路剖析。

⚽️(一)数据取值

    🔭之所以在Java代码层面去做数据处理是因为我们在数据库层面sql语句不好处理复杂业务数据,或者没有能直接可用的函数供给我们使用,我们才会想到用代码实现逻辑更便捷一些。(这里提一嘴:有些sql不好处理的业务,交给Java Stream流会给你意想不到的简单惊喜哦!当然这里我没用到Stream流,因为我也是刚在这个项目中接触一丢丢,用得确实不6,以后当然会666 🎯O(∩_∩)O哈哈~🎯)

    🍻① 首先看一下我们的需求,拿上周七天的均值数据,那么取七天的数据是必然的。之前的文章有讲过易犯错点:“不要频繁滴访问数据库”,所以我们的做法是直接在数据库中取七天的原始数据在sql层面不做任何处理。这里也有一个“踩坑”环节,不是拿过去七天,而是拿上周七天。所以,我们还需有有一个判断环节,这个判断是要根据目前的日期往前推算:今天是周几,然后往前推算几天才能拿到上周每一天的数值。这个判断环节如果曲线图在项目中运用较多,可以将其封装成一个方法,不管是我们自己开发,还是后期同事进行维护代码会更轻松便捷。这里是借助Java DateUtil类自带方法,利用该方法判断今天是一周中的周几,然后进行逻辑判断,具体代码如下所示:

	  DateTime dateTime = DateUtil.date();
      Week week = DateUtil.dayOfWeekEnum(dateTime);
      Integer day = 0;

      switch (week){
          case MONDAY:
              day = 1;
              break;
          case TUESDAY:
              day = 2;
              break;
          case WEDNESDAY:
              day = 3;
              break;
          case THURSDAY:
              day = 4;
              break;
          case FRIDAY:
              day = 5;
              break;
          case SATURDAY:
              day = 6;
              break;
          case SUNDAY:
              day = 7;
              break;
          default:
              day = 0;
              break;
      }

    🍻② 确认完今日是当前周的第几天后,还要限定在哪个时间范围内,并将时间格式化成正确的传入参数,参考代码如下所示:

  //日期往前推day+6位开始时间,往前推day-1为截止时间
  LocalDate beginLocalDate = LocalDate.now().minusDays(day+6);
  LocalDate endLocalDate = LocalDate.now().minusDays(day-1);

  //时间格式化
  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  String beginFormat = dateTimeFormatter.format(beginLocalDate);
  String endFormat = dateTimeFormatter.format(endLocalDate);
  
  //在年月日的基础上加上时分秒
  String beginTime = beginFormat + " 00:00:00";
  String endTime = endFormat + " 00:00:00";
  
  //String转Date格式
  Date beginDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(beginTime);
  Date endDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(endTime);

    🍻③ 确认完开始时间和截止时间后,将beginDate 和 endDate 作为Mapper接口的入参查询数据即可完成数据取值的任务,参考代码如下:

List<?> lastWeekList= xxxMapper.selectXXX(beginDate, enDate);
//对应的Mapper接口省略,基本操作大家都会写。

    🍗由于项目用的是ClickHouse数据库,诸多写法跟MySQL不同,mysql的Group by是比较友好的,但是要用CK的Group By,小伙伴试试就知道里面的坑是超级多的,你要查询多个字段,那么那些字段都需要Group By,带查询条件的基本都是要这样做,用得痛苦不堪… …

    🍗提供用于ClickHouse中分组的友好函数(超好用),将时间按照五分钟间隔统计数据,如果大家也是用到了CK可以试试看,如果不是CK的话,mysql处理要好得多不用搞得这么复杂,ck时间函数参考以下:

formatDateTime(toStartOfInterval(loadtime, INTERVAL 5 minute ),'%T') as lastWeekLoadTime

⚽️(二)时间坐标轴的选定

    🍔原始数据取好之后,下一步开始处理数据,处理数据要想好值如何摆放的问题,就像水浒英雄排座次一样的道理,本来在哪的就在哪,摆放不能搞乱了,否则影响的是前端展示效果,造成数据扭曲。

    🍔坐标轴的选取,这里不能用数据库中查询的时间作为坐标轴。原因有二:
🍻(1)假设当前时间是没有数据的,那么在数据库中某一条或者某多条数据是缺失的,虽然后台程序不会报错,但是整体返回的值相对而言少了;
🍻(2)返回值一旦空缺,前端会以某个接口的时间点作为坐标轴画曲线,没有的值前端那边是无法简单进行判断的,他不会自动进行补值,而是会将值给顶出去,假设现在为16:00,但是数据库中的值为17:00,16:00~17:00中间是没有数值的,前端不会显示16:00,而是会直接那17:00之后的数据顶上。这样造成的后果就是,图形化展示出未来的时间,哦豁,有bug哦!

    🍧解决办法当然有,我们用自定义方法作为坐标轴,好处就是这条坐标轴是固定不变的,不会因为某个时间点上没有数据而不存在的问题,获取固定时间间隔的方法参考如下代码:

	/**
     * 获取固定时间间隔
     */
    public static List<String> getIntervalTimeList(String start, String end, int interval) {
        Date startDate = convertString2Date("HH:mm:ss", start);
        Date endDate = convertString2Date("HH:mm:ss", end);
        List<String> list = new ArrayList<>();
        while (startDate.getTime() <= endDate.getTime()) {
            list.add(convertDate2String("HH:mm:ss", startDate));
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            calendar.add(Calendar.MINUTE, interval);
            if (calendar.getTime().getTime() > endDate.getTime()) {
                if (!startDate.equals(endDate)) {
                    list.add(convertDate2String("HH:mm:ss", endDate));
                }
                startDate = calendar.getTime();
            } else {
                startDate = calendar.getTime();
            }

        }
        return list;
    }

    🍧以上方法返回一个以interval为时间间隔,类型为String的timeList,我们传入参数也是要注意的,根据时间间隔来确认我们的start 和 end 具体为什么,参考代码如下:

//timeList长度为289,间隔五分钟288个数据, 间隔十分钟144个数据
List<String> timeList = DateUtils.getIntervalTimeList("00:00:00", "23:55:00", 5);

⚽️(三)结果的返回

    👑前两步的基础打好之后,后面的工作就好处理了,只需要将查询到的数据跟坐标轴进行匹配,匹配到之后整除7后进行返回,如果某个时间点没有值则可以返回null或者0,最终返回一个以interval为时间间隔完整的时间曲线。实例代码如下所示:

	List<?> list = new ArrayList();
	
	for (int i = 0; i < timeList.size(); i++) {
	   //业务逻辑匹配处理
	   Data data = new Data();
	
	   String lastWeekLoadTime = lastWeekList.get(i).getLastWeekLoadTime();
	   Integer num = 0;
	    
	   if (lastWeekLoadTime.equals(timeList.get(i))){
	       num = lastWeekList.get(i).getNum();
	   }
	
	   num /= 7;
	
	   String passTime = "2022-11-28 " + timeList.get(i);
	
	   data.setLoadtime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(passTime));
	   data.setNum(num);
	   list.add(data); 
	}
	
	return list;

⚽️(四)结语

🍰🍰🍰整个流程下来,主要是在代码层面对数据进行了一系列的处理。思路并不是一成不变的,需要时时刻刻撬动自己的脑筋才能把一个需求问题搞定。之前本人一直想在sql层面一次性把问题给解决了,左思右想最后发现自己根本不知道怎么动手合适。最终想到用传参到sql中和自定义方法解决问题,面临自己之前没接触过的数据库确实很多地方都是知识盲区,这个时候要多请教一下解决过相关业务的同事,多在网上寻求解决方案,希望自己的这点经历也能成为你们的“答案”🍭🍭🍭

🍆🍆🍆路过的小伙伴,如果本篇博文对你的学习或者工作有所帮助,可以点赞+收藏+关注一波呀~👊👊👊小编后续每过一段时间会整理出相关项目实例的博文,感谢您的支持哦!!!✈️✈️✈️
在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fish_Vast

您的打赏是对我最大的支持!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值