使用SQL按每小时统计数据的方法

在数据分析和报表生成中,按小时统计数据是一个常见的需求。无论是监控系统的运行状态,还是分析用户行为模式,小时级别的数据统计都能提供细致且有价值的信息。

需要知道

时间戳与时间格式

在SQL数据库中,时间数据通常以时间戳的形式存储。时间戳是一个表示特定时间点的整数,通常以毫秒或秒为单位。例如,1521008160000就是一个13位的毫秒级时间戳。

时间函数

MySQL提供了一系列时间函数,用于处理和转换时间数据。常用的函数包括:

  • FROM_UNIXTIME():将Unix时间戳转换为日期时间格式。
  • DATE_FORMAT():根据指定的格式显示日期时间数据。
  • HOUR():从时间值中提取小时部分。

按小时统计数据的实现方法

简单的时间转换与分组

假设我们有一个名为dspreport的表,其中包含一个名为hourtime的列,存储的是毫秒级时间戳。我们可以使用以下SQL查询按小时分组统计数据:

sql 复制代码
SELECT 
    FROM_UNIXTIME(hourtime / 1000, '%Y-%m-%d %H') AS hour,
    COUNT(*) AS count
FROM 
    dspreport
GROUP BY 
    FROM_UNIXTIME(hourtime / 1000, '%Y-%m-%d %H');

这个查询首先将毫秒级时间戳转换为秒级时间戳,然后使用FROM_UNIXTIME()函数将其转换为YYYY-MM-DD HH格式的字符串,最后按这个字符串分组并计数。

使用DATE_FORMAT()函数

另一种方法是使用DATE_FORMAT()函数,直接对时间戳进行格式化:

sql 复制代码
SELECT 
    DATE_FORMAT(FROM_UNIXTIME(hourtime / 1000), '%Y-%m-%d %H') AS hour,
    COUNT(*) AS count
FROM 
    dspreport
GROUP BY 
    DATE_FORMAT(FROM_UNIXTIME(hourtime / 1000), '%Y-%m-%d %H');

这种方法与第一种方法类似,但DATE_FORMAT()函数提供了更多的格式化选项,更加灵活。

示例

示例一:查询某个时间段内各个小时的访客人数

首先我们需要一个表来存储访客的访问记录。这个表至少需要包含两个字段:visit_time(访问时间)和ip(访客的IP地址)。例如:

sql 复制代码
CREATE TABLE visitor_logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  ip VARCHAR(50) NOT NULL,
  visit_time DATETIME NOT NULL
);

接着写出按小时查询访客人数的sql:

go 复制代码
SELECT
  HOUR(visit_time) AS hour,
  COUNT(DISTINCT ip) AS visitor_count
FROM
  visitor_logs
WHERE
  visit_time BETWEEN '开始时间' AND '结束时间'
GROUP BY
  HOUR(visit_time);

如果想要不区分是否为独立访客,只想要得到被访问次数的话,可以将COUNT (DISTINCT ip)改为COUNT(*)

需要注意的是:如果使用的是 PostgreSQL ,可能会因为 PostgreSQL 没有内置的 HOUR 函数而收到错误提示: "function hour(timestamp without time zone) does not exist",可以换成 EXTRACT 函数来获取时间戳中的小时部分

示例二:查询每小时内新建对话次数

部分数据库表如下图所示:

我们按照上面的方法,编写sql来查询每小时内新建对话数:

sql 复制代码
SELECT EXTRACT(HOUR FROM created_at) as hour, COUNT(*) as conversation_count 
FROM conversations 
WHERE created_at BETWEEN '2024-11-19 07:03:28.09' AND '2024-11-26 07:03:28.09' 
GROUP BY EXTRACT(HOUR FROM created_at) 
ORDER BY hour

运行该sql得出以下结果:

但是与数据库中的数据做比较后,很容易发现问题:

其中在不同日期但同一时间的数据被归纳到了一起。

为了解决这个问题,我们需要在原SQL上做一些"升级"

sql 复制代码
SELECT DATE(created_at) as date, EXTRACT(HOUR FROM created_at) as hour, COUNT(*) as conversation_count 
FROM conversations 
WHERE created_at BETWEEN '2024-11-19 07:03:28.09' AND '2024-11-26 07:03:28.09' 
GROUP BY DATE(created_at), EXTRACT(HOUR FROM created_at) 
ORDER BY date, hour

之后我们再创建一个结构体来接收得到的数据,就可以啦

go 复制代码
type ChartData []struct {
	Date  time.Time `gorm:"column:date"`
	Hour  int       `gorm:"column:hour"`
	Count int       `gorm:"column:count"`
}

sql := "SELECT DATE(created_at) as date, EXTRACT(HOUR FROM created_at) as hour, COUNT(*) as conversation_count FROM conversations WHERE created_at BETWEEN '2024-11-19 07:03:28.09' AND '2024-11-26 07:03:28.09' GROUP BY DATE(created_at),EXTRACT(HOUR FROM created_at) ORDER BY date, hour"
datas := ChartData{}
err := db.Raw(sql,StartTime,EndTime)//这里StartTime和EndTime可以是提前定义或从前端获取等

最终我们可以得到一个这样的东西:

go 复制代码
[{2024-11-20 00:00:00 +0000 UTC 8 2} 
{2024-11-21 00:00:00 +0000 UTC 8 1} 
{2024-11-21 00:00:00 +0000 UTC 9 2} 
{2024-11-21 00:00:00 +0000 UTC 10 4} 
{2024-11-22 00:00:00 +0000 UTC 9 1}]
相关推荐
无名之逆几秒前
[特殊字符] Hyperlane 框架:高性能、灵活、易用的 Rust 微服务解决方案
运维·服务器·开发语言·数据库·后端·微服务·rust
爱的叹息20 分钟前
MongoDB 的详细解析,涵盖其核心概念、架构、功能、操作及应用场景
数据库·mongodb·架构
慕离桑1 小时前
SQL语言的物联网
开发语言·后端·golang
欧宸雅1 小时前
Swift语言的游戏引擎
开发语言·后端·golang
爱的叹息1 小时前
华为高斯(GaussDB)数据库中 Range、List、Hash三种分区方式 的完整SQL示例及增删改查操作,并附上总结对比表格
数据库·哈希算法·gaussdb
霍珵蕴2 小时前
Kotlin语言的软件工程
开发语言·后端·golang
程序猿熊跃晖2 小时前
Excel 数据导入与 SQL 生成:基于 Hutool 和 Apache POI 的优雅实践
sql·apache·excel
kfepiza2 小时前
Debian用二进制包安装mysql8.0.41 笔记250401
数据库·笔记·mysql·debian·database
在努力的韩小豪3 小时前
B树和B+树的区别(B Tree & B+ Tree)
数据结构·数据库·b树·b+树·索引·数据库索引
褚翾澜3 小时前
Bash语言的社区交流
开发语言·后端·golang