MySQL 中只統(tǒng)計周一到周五的到訪數(shù)據(jù)(案例演示)
在醫(yī)院信息系統(tǒng)中,我們經(jīng)常需要統(tǒng)計各種業(yè)務(wù)數(shù)據(jù),例如門診到訪人數(shù)、掛號量、就診量等。
但一個常見需求是:
只統(tǒng)計工作日(周一 ~ 周五),周六周日不算!
乍一看很簡單,但在實際數(shù)據(jù)庫中,如果處理不好,很容易出現(xiàn):
- 查詢很慢(全表掃描 ALL)
- 索引用不上(在字段上套函數(shù))
- 數(shù)據(jù)量大時 CPU 飆高
- 報表卡頓
一、業(yè)務(wù)背景
某醫(yī)院有一張到訪記錄表:
CREATE TABLE IF NOT EXISTS t_visit (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
hospital_id INT,
creatime DATETIME,
visit_num INT
);每天有大量患者到訪,后臺需要統(tǒng)計:
每家醫(yī)院在最近一個月的工作日到訪總?cè)藬?shù)(排除周六周日)
二、初級寫法(反面案例)
SELECT
SUM(visit_num)
FROM t_visit
WHERE WEEKDAY(creatime) < 5;
這看似正確,但這會導(dǎo)致:
問題 1:索引用不上
因為你對 creatime 使用了函數(shù):
WEEKDAY(creatime)
使得 MySQL 無法利用索引,explain 一般是:
type: ALL rows: 全表行數(shù)

問題 2:數(shù)據(jù)量大時性能災(zāi)難
醫(yī)院一天幾十萬條,一年幾千萬條,
全表掃 + 函數(shù)計算,直接拖垮服務(wù)器。
所以這不是企業(yè)級可接受的寫法。
三、基礎(chǔ)優(yōu)化寫法(適合中小數(shù)據(jù)量)
加上時間范圍,利用 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;優(yōu)勢:
- MySQL 會先利用時間范圍做索引掃描
- 再對掃描結(jié)果執(zhí)行 weekday 過濾
- 比全表掃好很多
但 WEEKDAY() 仍然不是最佳方案。

四、企業(yè)實戰(zhàn)解決方案
方案 1:生成列(STORED)+ 索引
醫(yī)院數(shù)據(jù)往往需要長期統(tǒng)計、同比環(huán)比、報表分析,
企業(yè)里最常用的做法是:
把星期幾提前算好,存在表里,并建立索引
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. 查詢變得非???/h4>
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;
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;

企業(yè)大部分系統(tǒng)都這么做。
方案 2:數(shù)據(jù)倉庫 / 報表系統(tǒng)的標(biāo)準(zhǔn):日期維表 dim_date
大型醫(yī)院(尤其三甲)數(shù)據(jù)量很大,
通常會有數(shù)據(jù)倉庫(DW)或 BI 系統(tǒng)。
在 DW 里幾乎必建:
日期維表(dim_date)
例子:
CREATE TABLE dim_date (
date_key DATE PRIMARY KEY,
weekday TINYINT,
is_workday TINYINT,
is_holiday TINYINT,
holiday_name VARCHAR(20)
);
再加關(guān)聯(lián)字段:
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;
優(yōu)勢:
- 查詢速度快(走索引)
- 節(jié)假日/補班規(guī)則可隨時調(diào)整
- 所有報表口徑統(tǒng)一
- 信息科、財務(wù)、運營都能復(fù)用這個維表

五、醫(yī)院真實案例演示
需求:統(tǒng)計 2025 年 1 月各醫(yī)院工作日的到訪人數(shù)
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;
輸出示例:

六、總結(jié)
能跑的是 SQL,能跑快的是架構(gòu)。
企業(yè)里處理“周一到周五統(tǒng)計”一般不會直接用 weekday 函數(shù),而是通過生成列或日期維表實現(xiàn)高性能統(tǒng)計。
到此這篇關(guān)于MySQL 中只統(tǒng)計周一到周五的到訪數(shù)據(jù)(案例演示)的文章就介紹到這了,更多相關(guān)mysql統(tǒng)計周一到周五數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL數(shù)據(jù)庫中SQL分組統(tǒng)計與排序詳解
- Mysql如何將數(shù)據(jù)按照年月分組的統(tǒng)計
- MySQL實現(xiàn)按分秒統(tǒng)計數(shù)據(jù)量方式
- MySQL數(shù)據(jù)庫統(tǒng)計函數(shù)COUNT的使用及說明
- MYSQL數(shù)據(jù)庫查詢按日期分組統(tǒng)計詳細(xì)代碼
- mysql如何分別按年/月/日/周分組統(tǒng)計數(shù)據(jù)詳解
- MySQL實現(xiàn)統(tǒng)計過去12個月每個月的數(shù)據(jù)信息
- MySQL如何統(tǒng)計一個數(shù)據(jù)庫所有表的數(shù)據(jù)量
- MySQL 如何設(shè)計統(tǒng)計數(shù)據(jù)表
相關(guān)文章
mysql安裝數(shù)據(jù)庫初始化失敗問題解決方法保姆級教程
這篇文章主要給大家介紹了關(guān)于mysql安裝數(shù)據(jù)庫初始化失敗問題解決方法保姆級教程,包括更改電腦名稱、確保防火墻設(shè)置、清理殘留文件、檢查權(quán)限和配置文件等,需要的朋友可以參考下2025-01-01
MySQL快速禁用賬戶登入及如何復(fù)制/復(fù)用賬戶密碼(最新推薦)
這篇文章主要介紹了MySQL如何快速禁用賬戶登入及如何復(fù)制/復(fù)用賬戶密碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01
阿里云服務(wù)器手動實現(xiàn)mysql雙機熱備的兩種方式
阿里云服務(wù)器由于不支持keepalive虛擬ip,導(dǎo)致無法通過keepalive來實現(xiàn)mysql的雙機熱備。我們這里要實現(xiàn)阿里云的雙機熱備有兩種方式。感興趣的朋友跟隨小編一起看看吧2019-10-10
MySQL之MHA高可用配置及故障切換實現(xiàn)詳細(xì)部署步驟
這篇文章主要介紹了MySQL之MHA高可用配置及故障切換實現(xiàn)詳細(xì)部署步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
MySQL命令行方式進行數(shù)據(jù)備份與恢復(fù)
本文主要介紹了MySQL命令行方式進行數(shù)據(jù)備份與恢復(fù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

