MySQL 中只统计周一到周五的到访数据(案例演示)

 更新时间:2025年12月10日 10:17:57   作者:Knight_AL  
文章介绍了如何在医院信息系统中高效统计工作日到访人数,避免全表扫描和索引失效的问题,通过生成列和使用日期维表,可以实现快速查询和报表分析,适用于大型医院的复杂数据量,感兴趣的朋友跟随小编一起看看吧

在医院信息系统中,我们经常需要统计各种业务数据,例如门诊到访人数、挂号量、就诊量等。
但一个常见需求是:

只统计工作日(周一 ~ 周五),周六周日不算!

乍一看很简单,但在实际数据库中,如果处理不好,很容易出现:

  • 查询很慢(全表扫描 ALL)
  • 索引用不上(在字段上套函数)
  • 数据量大时 CPU 飙高
  • 报表卡顿

一、业务背景

某医院有一张到访记录表:

CREATE TABLE IF NOT EXISTS t_visit (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    hospital_id INT,
    creatime    DATETIME,
    visit_num   INT
);

每天有大量患者到访,后台需要统计:

每家医院在最近一个月的工作日到访总人数(排除周六周日)

二、初级写法(反面案例)

SELECT
    SUM(visit_num)
FROM t_visit
WHERE WEEKDAY(creatime) < 5;

这看似正确,但这会导致:

问题 1:索引用不上

因为你对 creatime 使用了函数:

WEEKDAY(creatime)

使得 MySQL 无法利用索引,explain 一般是:

type: ALL
rows: 全表行数

问题 2:数据量大时性能灾难

医院一天几十万条,一年几千万条,
全表扫 + 函数计算,直接拖垮服务器。

所以这不是企业级可接受的写法。

三、基础优化写法(适合中小数据量)

加上时间范围,利用 creatime 索引进行范围扫描

CREATE INDEX idx_visit_creatime ON t_visit(creatime);

查询:

EXPLAIN
SELECT
    SUM(visit_num)
FROM t_visit
WHERE 
    creatime >= '2025-01-01'
    AND creatime <  '2025-02-01'
    AND WEEKDAY(creatime) < 5;
		EXPLAIN
SELECT
    SUM(visit_num)
FROM t_visit FORCE INDEX (idx_visit_creatime)
WHERE 
    creatime >= '2025-01-01'
    AND creatime <  '2025-02-01'
    AND WEEKDAY(creatime) < 5;

优势:

  • MySQL 会先利用时间范围做索引扫描
  • 再对扫描结果执行 weekday 过滤
  • 比全表扫好很多

WEEKDAY() 仍然不是最佳方案。

四、企业实战解决方案

方案 1:生成列(STORED)+ 索引

医院数据往往需要长期统计、同比环比、报表分析,
企业里最常用的做法是:

把星期几提前算好,存在表里,并建立索引

1. 增加生成列

ALTER TABLE t_visit
  ADD COLUMN weekday TINYINT AS (WEEKDAY(creatime)) STORED,
  ADD COLUMN is_workday TINYINT(1) AS (
    CASE WHEN WEEKDAY(creatime) < 5 THEN 1 ELSE 0 END
  ) STORED,
  ADD INDEX idx_visit_workday (is_workday, creatime);
  • weekday:0=周一,6=周日
  • is_workday:1=工作日,0=周末

2. 查询变得非常快

SELECT
    hospital_id,
    SUM(visit_num)
FROM t_visit
WHERE 
    is_workday = 1        -- 索引用得上!
    AND creatime BETWEEN '2025-01-01' AND '2025-02-01'
GROUP BY hospital_id;

企业大部分系统都这么做。

方案 2:数据仓库 / 报表系统的标准:日期维表 dim_date

大型医院(尤其三甲)数据量很大,
通常会有数据仓库(DW)或 BI 系统。

在 DW 里几乎必建:

日期维表(dim_date)

例子:

CREATE TABLE dim_date (
    date_key    DATE PRIMARY KEY,
    weekday     TINYINT,
    is_workday  TINYINT,
    is_holiday  TINYINT,
    holiday_name VARCHAR(20)
);

再加关联字段:

ALTER TABLE t_visit
  ADD COLUMN visit_date DATE AS (DATE(creatime)) STORED,
  ADD INDEX idx_visit_date (visit_date);

然后:

SELECT
    v.hospital_id,
    SUM(v.visit_num) AS total_visit
FROM t_visit v
JOIN dim_date d
    ON v.visit_date = d.date_key
WHERE 
    d.is_workday = 1
    AND v.visit_date BETWEEN '2025-01-01' AND '2025-02-01'
GROUP BY v.hospital_id;

优势:

  • 查询速度快(走索引)
  • 节假日/补班规则可随时调整
  • 所有报表口径统一
  • 信息科、财务、运营都能复用这个维表

五、医院真实案例演示

需求:统计 2025 年 1 月各医院工作日的到访人数

SQL:

SELECT
    v.hospital_id,
    d.is_workday,
    SUM(v.visit_num) AS visit_total,
    COUNT(*) AS visit_times
FROM t_visit v
JOIN dim_date d
    ON v.visit_date = d.date_key
WHERE
    v.visit_date >= '2025-01-01'
    AND v.visit_date <  '2025-02-01'
    AND d.is_workday = 1       -- 只算工作日
GROUP BY v.hospital_id, d.is_workday
ORDER BY hospital_id;

输出示例:

六、总结

能跑的是 SQL,能跑快的是架构。
企业里处理“周一到周五统计”一般不会直接用 weekday 函数,而是通过生成列或日期维表实现高性能统计。

到此这篇关于MySQL 中只统计周一到周五的到访数据(案例演示)的文章就介绍到这了,更多相关mysql统计周一到周五数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql安装数据库初始化失败问题解决方法保姆级教程

    mysql安装数据库初始化失败问题解决方法保姆级教程

    这篇文章主要给大家介绍了关于mysql安装数据库初始化失败问题解决方法保姆级教程,包括更改电脑名称、确保防火墙设置、清理残留文件、检查权限和配置文件等,需要的朋友可以参考下
    2025-01-01
  • MySQL快速禁用账户登入及如何复制/复用账户密码(最新推荐)

    MySQL快速禁用账户登入及如何复制/复用账户密码(最新推荐)

    这篇文章主要介绍了MySQL如何快速禁用账户登入及如何复制/复用账户密码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • 一文详解如何彻底删除旧版本mysql并安装新版本

    一文详解如何彻底删除旧版本mysql并安装新版本

    如果要重新安装MySQL就必须将之前的MySQL进行彻底的卸载,下面这篇文章主要给大家介绍了关于如何彻底删除旧版本mysql并安装新版本的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • mysql 按中文字段排序

    mysql 按中文字段排序

    在MySQL中,进行中文排序和查找的时候,对汉字的排序和查找结果是错误的。 这种情况在MySQL的很多版本中都存在。
    2009-01-01
  • Suse Linux 10中MySql安装与配置步骤

    Suse Linux 10中MySql安装与配置步骤

    这篇文章主要介绍了Suse Linux 10中MySql安装与配置步骤,本文详细的讲解了安装步骤,需要的朋友可以参考下
    2015-05-05
  • 阿里云服务器手动实现mysql双机热备的两种方式

    阿里云服务器手动实现mysql双机热备的两种方式

    阿里云服务器由于不支持keepalive虚拟ip,导致无法通过keepalive来实现mysql的双机热备。我们这里要实现阿里云的双机热备有两种方式。感兴趣的朋友跟随小编一起看看吧
    2019-10-10
  • MySQL之MHA高可用配置及故障切换实现详细部署步骤

    MySQL之MHA高可用配置及故障切换实现详细部署步骤

    这篇文章主要介绍了MySQL之MHA高可用配置及故障切换实现详细部署步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • MySql数据库分布式存储配置实操步骤

    MySql数据库分布式存储配置实操步骤

    这篇文章主要为大家介绍了MySql数据库分布式存储配置实操步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 详细解读MySQL的触发器trigger

    详细解读MySQL的触发器trigger

    触发器是由事件来触发某个操作,这些事件包括INSERT、UPDATE和DELETE语句。如果定义了触发程序,当数据库执行这些语句的时候就会激发触发器执行相应的操作,需要的朋友可以参考下
    2023-05-05
  • MySQL命令行方式进行数据备份与恢复

    MySQL命令行方式进行数据备份与恢复

    本文主要介绍了MySQL命令行方式进行数据备份与恢复,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论