连续时间折线图的前后端实现

技术栈

  • vue3
  • VChart
  • egg.js
  • MySQL

需求

根据已有任务数据,获取连续天的任务完成的数量,并且通过接口返回后做成图表。预期数据如下:

[{"x": "2024-01-01","y": 0},{"x": "2024-01-02","y": 26},{"x": "2024-01-03","y": 43},{"x": "2024-01-04","y": 39},{"x": "2024-01-05","y": 22},{"x": "2024-01-06","y": 0},// ...
]

非连续数据

最简单的查询方式当然就是 GROUP BY 了,但是呢有些日期里面是没有任何数据的。

SELECTDATE (FinishTime),COUNT(*) AS count
FROMtasks
WHEREFinishTime >= '2024-01-01'AND FinishTime <= '2024-02-01'
GROUP BYDATE (FinishTime)

所以需要手动补全这些日期,将其数据设置为 0。网上查了一些方案,有不少骚操作,不过我还是更喜欢和日期表联表查询的方式。感觉这种更合理些。

插入日期表

在建表后,我是通过 node 遍历的方式插入的数据,感觉很 low 的方式……不过暂时能用就行。后面再学习更优雅的写法。

const Service = require('egg').Service
const dayjs = require('dayjs')class DateService extends Service {async createDates() {const startDay = dayjs().subtract(600, 'day')for (let i = 0; i < 1000; i++) {const currentDateStr = startDay.add(i, 'day').format('YYYY-MM-DD')await this.app.mysql.insert('dates', {date: currentDateStr,})}return '插入成功'}
}module.exports = DateService

运行起来很慢,慢慢悠悠的用 dayjs 插入最近的 1000 条日期数据。

联表查询任务量 SQL 写法

在有了两个表后,就可以使用 LEFT JOIN 来进行联表查询了。由于要补全连续日期,所以先查日期表,然后再联表查询了任务表。

    SELECTDATE(dt.dt_date) as x,IFNULL (tk.tk_count, 0) AS y
FROM(SELECTDATE (date) AS dt_dateFROMdatesWHEREdate >= '2024-01-01'AND date <= '2024-02-01) dtLEFT JOIN (SELECTDATE (FinishTime) as tk_date,COUNT(*) AS tk_countFROMtasksWHEREFinishTime >= '2024-01-01AND FinishTime <= '2024-02-01'GROUP BYDATE (FinishTime)) tk ON dt.dt_date = tk.tk_date

用 AI GPT 优化下:

SELECTDATE(dt.dt_date) AS x,COALESCE(tk.tk_count, 0) AS y
FROM (SELECTDATE(date) AS dt_dateFROMdatesWHEREdate BETWEEN '2024-01-01' AND '2024-02-01'
) dt
LEFT JOIN (SELECTDATE(FinishTime) AS tk_date,COUNT(*) AS tk_countFROMtasksWHEREFinishTime BETWEEN '2024-01-01' AND '2024-02-01'GROUP BYDATE(FinishTime)
) tk ON dt.dt_date = tk.tk_date;

如此就感觉优雅多了。

图形渲染

有始有终,最后把任务量以折线图的方式呈现出来~

node 端进行接口实现

 async getTaskCount() {const { start_date, end_date } = this.ctx.query// 这里做了简单的正则匹配const reg = /^\d{4}-\d{2}-\d{2}$/if (!reg.test(start_date) || !reg.test(end_date)) {return []}const sql = `SELECTDATE(dt.dt_date) as x,IFNULL (tk.tk_count, 0) AS y
FROM(SELECTDATE (date) AS dt_dateFROMdatesWHEREdate >= ?AND date <= ?) dtLEFT JOIN (SELECTDATE (FinishTime) as tk_date,COUNT(*) AS tk_countFROMtasksWHEREFinishTime >= ?AND FinishTime <= ?GROUP BYDATE (FinishTime)) tk ON dt.dt_date = tk.tk_date`const result = await this.app.mysql.query(sql, [start_date,end_date,start_date,end_date,])return result}

前端部分通过 VChart 快速渲染

<template><!-- 为 vchart 准备一个具备大小(宽高)的 DOM,当然你也可以在 spec 配置中指定 --><div id="chart" style="width: 600px; height: 400px"></div>
</template><script setup>
import axios from 'axios'
import VChart from '@visactor/vchart'import { onMounted, ref } from 'vue'onMounted(() => {getChartData()
})const chartData = ref([])function getChartData() {return axios.get('/api/yang/chart', {params: {start_date: '2024-01-01',end_date: '2024-02-01',},}).then(({ data }) => {chartData.value = datarenderChart()})
}function renderChart() {const spec = {type: 'line',data: {values: chartData.value,},xField: 'x',yField: 'y',}const vchart = new VChart(spec, { dom: 'chart' })// 创建 vchart 实例// 绘制vchart.renderSync()
}
</script><style lang="scss" scoped></style>

效果图如下,非常完美~

image

整理一些学到的后端知识

  • 查询的目标不一定非得是固定的表,也可以用 () 括号来查询目标数据集。无论是 FROM 还是 LEFT JOIN 都是如此。
  • IFNULL() 函数可以在数据为空的时候返回一个默认值。
  • COALESCE() 函数也是用来处理缺失值的,感觉和 IFNULL 差不多。
  • 查询日期范围的时候,不需要连续用大于等于小于加上 AND,可以直接用 BETWEEN…AND… 来实现。
  • DATE() 函数可以从日期、时间数据中提取日期部分,如 YYYY-MM-DD。
  • MySQL 服务器也分好多版本,网上资料来看 8.0+ 是最新的,而稳定版本一般是 5.7。另外如果想切换云服务器的 MySQL 版本需要备份删库……
  • 在 egg.js 中需要在 mysql 配置中打开 dateStrings: true 来确保时区为当前时区。否则存取日期的时候会差八个小时(东八区)。

最后

以上就是我在学习图表后端接口实现的过程中的一些心得,感觉数据方向上 SQL 的各种应用还是很广的,可以通过各种不同维度、指标、筛选条件,产出各类不同数据。

可以预见后面可以折腾的东西还有很多~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python实现KDJ工具判断信号:股票技术分析的工具系列(8)

Python实现KDJ工具判断信号&#xff1a;股票技术分析的工具系列&#xff08;8&#xff09; 介绍算法公式 代码rolling函数介绍完整代码data代码KDJ.py 介绍 KDJ是一种技术指标&#xff0c;用于衡量价格动量&#xff0c;帮助交易者识别趋势的强度和转折点。 先看看官方介绍&am…

Vue入门篇:概念,快速入门,插值表达式,核心特性,基本Vue指令

目录 1.Vue是什么2.快速入门3.插值表达式{{}}1.作用:2.语法:3.插值表达式的注意点: 4.Vue响应式核心特性5.Vue指令 1.Vue是什么 Vue是一个流行的JavaScript框架&#xff0c;用于构建用户界面。它是一种用于构建单页面应用程序&#xff08;SPA&#xff09;的渐进式框架&#xff…

机器学习系统的设计

1.混淆矩阵 混淆矩阵作用就是看一看在测试集样本集中&#xff1a; 真实值是 正例 的样本中&#xff0c;被分类为 正例 的样本数量有多少&#xff0c;这部分样本叫做真正例&#xff08;TP&#xff0c;True Positive&#xff09;&#xff0c;预测为真&#xff0c;实际为真真实值…

NtripShare2024年第一季度主要技术进展

迷迷糊糊又是一个月没有写点什么&#xff0c;近期想清楚NtripShare在2024的要做什么事情&#xff0c;暂且将NtripShare要做的主要事情为搭建由软件与硬件之间的技术桥梁。 在过去的几年时间里NtripShare对硬件方面一直是规避的态度&#xff0c;今年开始要做一点软硬件搭界的技…

mmcv bug记录

图像分类任务要用到mmcv框架&#xff0c;记录遇到的问题 1. Can‘t import build_from_cfg from mmcv. 解决命令&#xff1a;pip install openmim && mim install mmcv-full 2. python分布式训练 解决方案&#xff1a; 租用多张A40卡&#xff0c;执行下述命令&…

跨站攻击CSRF实验

1.low等级 先利用Burp抓包 将get响应的url地址复制&#xff0c;发到网页上&#xff08;Low等级到这完成&#xff09; Medium&#xff1a; 再将抓到的包发到Repeater上,对请求中的Referer进行修改&#xff0c;修改成和url一样的地址&#xff0c;修改成功。 在这里修改后发送 然…

团队协作:如何利用 Gitee 实现多人合作项目的版本控制

文章目录 前言一、名词解释1、Git是什么&#xff1f;2、Gitee、GitHub和GitLab 二、操作步骤1.安装Git2.创建Gitee仓库3.用vscode连接仓库4. 克隆远程仓库 总结 前言 在软件开发中&#xff0c;有效地管理代码是至关重要的。Gitee 是一个功能强大的代码托管平台&#xff0c;提供…

使用clickhouse-backup迁移数据

作者&#xff1a;俊达 1 说明 上一篇文章中&#xff0c;我们介绍了clickhouse-backup工具。除了备份恢复&#xff0c;我们也可以使用该工具来迁移数据。 这篇文章中&#xff0c;我们提供一个使用clickhouse-backup做集群迁移的方案。 2 前置条件 1、源端和目标端网络联通&a…

LeetCode刷题实战5:最长回文子串

题目内容 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba"…

k8s 控制器StatefulSet原理解析

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、k8s概述 2、有状态服务和无状态服务…

von Mises-Fisher Distribution (代码解析)

torch.distribution 中包含了很多概率分布的实现&#xff0c;本文首先通过均匀分布来说明 Distribution 的具体用法, 然后再解释 von Mises-Fisher 分布的实现, 其公式推导见 von Mises-Fisher Distribution. 1. torch.distribution.Distribution 以下是 Uniform 的源码: cl…

C++语言·类和对象(下)

1. 初始化列表 我们回忆上节写的MyQueue类&#xff0c;其中有两个栈类和一个int类型&#xff0c;栈类因为其特殊性&#xff0c;要开空间&#xff0c;所以我们必须手搓Stack类的构造函数。但是正常来说MyQueue自动生成的构造函数会调用自定义类型的默认构造函数&#xff0c;也就…

基于SpringBoot+Vue的体检管理系统 免费获取源码

项目源码获取方式放在文章末尾处 项目技术 数据库&#xff1a;Mysql5.7/8.0 数据表&#xff1a;12张 开发语言&#xff1a;Java(jdk1.8) 开发工具&#xff1a;idea 前端技术&#xff1a;vue html 后端技术&#xff1a;SpringBoot 功能简介 (有文档) 项目获取关键字&…

浏览器渲染流程中的 9 个面试点

记得 08 年以前&#xff0c;打开网页的时候一个页面卡死整个浏览器凉凉。 这是因为当时浏览器是单进程架构&#xff0c;一个页面或者插件卡死&#xff0c;整个浏览器都会崩溃&#xff0c;非常影响用户体验。 经过了一代代工程师的设计&#xff0c;现代浏览器改成了多进程架构&…

异常检测 | SVDD支持向量数据描述异常数据检测(Matlab)

异常检测 | SVDD支持向量数据描述异常数据检测&#xff08;Matlab&#xff09; 目录 异常检测 | SVDD支持向量数据描述异常数据检测&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 用于一类或二元分类的 SVDD 模型 多种核函数&#xff08;…

医学临床预测模型发展新趋势-并联式

医学临床预测模型发展新姿势-并联式 现有的预测模型是对单个结局指标进行分类或者回归&#xff0c;得出最终的结论&#xff0c;而辅助医生进行临床决策。众所周知&#xff0c;临床决策过程中&#xff0c;医生通常会考虑多个结局指标来做出最终的决策&#xff1b;临床研究中也通…

网络编程初步

协议&#xff1a; 一组规则 分层模型结构&#xff1a; OSI七层模型&#xff1a;物、数、网、传、会、表、应 TCP/IP 4层模型&#xff1a;网&#xff08;链路层/网络接口层)、网、传、应 应用层&#xff1a;http、 ftp、 nfs、 ssh、 telneto o .传输层:TCP、UDP 网络层&…

【干货精品分享】Elasticsearch 6.7 Should 子语句的失效

在ES 使用多条件 查询&#xff0c;并且是多个条件只需要满足部分条件的时候&#xff0c;我们通常会使用到ES的should查询 GET /trademark_query_index/_search {"query":{"bool" : {"must":[{"match" : {"origin": {"…

229 基于matlab的网络入侵检测问题

基于matlab的网络入侵检测问题&#xff0c;主要使用有监督的Kohonen神经网络。有监督Kohonen神经网络的网络结构为38-36-5&#xff0c;网络训练结果受权值影响相当大。在算法初期&#xff0c;本文引入杂草算法对Kohonen网络进行权值寻优。文件包括&#xff1a;入侵数据(data.ma…

网站备案期间怎么关闭首页显示无法访问-文章及其它页面正常访问

自从做了开发者之后才发现每个人博主的需求都是不同的&#xff0c;的的确确颠覆了我的观点&#xff0c;无论是页面布局还是SEO相关的设置&#xff0c;可能是因为站点属性不同所以需求不同&#xff0c;慢慢的就会在主题加入一些自定接口来满足不同人的需求&#xff0c;有人需要P…