数据库——MySQL数字函数和子查询

一、数据库表结构设计

1. 患者表(patient)

记录患者基本信息:

sql 复制代码
CREATE TABLE patient (
    patientID INT PRIMARY KEY,
    patientName VARCHAR(50),
    birthDate DATE
);

示例数据

sql 复制代码
INSERT INTO patient VALUES
(1, '姚维新', '1990-05-15'),
(2, '夏颖', '1985-03-20'),
(3, '张三', '2000-01-10'),
(4, '李四', '1975-07-30'),
(5, '简要选', '1980-12-25');

2. 检查记录表(prescription)

记录患者的检查记录:

sql 复制代码
CREATE TABLE prescription (
    prescriptionID INT PRIMARY KEY,
    patientID INT,
    checkItemID INT,
    examDate DATE
);

示例数据

sql 复制代码
INSERT INTO prescription VALUES
(1, 2, 1, '2022-01-15'),
(2, 2, 1, '2023-01-10'),
(3, 1, 1, '2021-05-20'),
(4, 3, 1, '2023-03-15'),
(5, 4, 1, '2020-11-30');

3. 检查项目表(checkitem)

定义检查项目类型:

sql 复制代码
CREATE TABLE checkitem (
    checkItemID INT PRIMARY KEY,
    checkItemName VARCHAR(50)
);

示例数据

sql 复制代码
INSERT INTO checkitem VALUES
(1, '血常规'),
(2, '尿常规'),
(3, '心电图');

二、基础数学函数详解

1. ABS() - 绝对值

语法ABS(number)
示例

sql 复制代码
SELECT ABS(-10) AS result; -- 输出:10

2. CEIL()/CEILING() - 向上取整

语法CEIL(number)
示例

sql 复制代码
SELECT CEIL(4.3) AS result; -- 输出:5
SELECT CEIL(-4.3) AS result; -- 输出:-4

3. FLOOR() - 向下取整

语法FLOOR(number)
示例

sql 复制代码
SELECT FLOOR(4.7) AS result; -- 输出:4
SELECT FLOOR(-4.3) AS result; -- 输出:-5

4. ROUND() - 四舍五入

语法ROUND(number, decimal_places)
示例

sql 复制代码
SELECT ROUND(4.567, 2) AS result; -- 输出:4.57
SELECT ROUND(4.567, 0) AS result; -- 输出:5

三、子查询实战案例

1. 查找做过"血常规"检查的患者

sql 复制代码
SELECT p.patientName 
FROM patient p
WHERE p.patientID IN (
    SELECT pr.patientID 
    FROM prescription pr
    JOIN checkitem ci ON pr.checkItemID = ci.checkItemID
    WHERE ci.checkItemName = '血常规'
);

输出

sql 复制代码
patientName
夏颖
姚维新
张三
李四

2. 显示每个患者的检查次数

sql 复制代码
SELECT p.patientName, 
       (SELECT COUNT(*) 
        FROM prescription 
        WHERE patientID = p.patientID) AS check_count
FROM patient p;

输出

sql 复制代码
patientName | check_count
姚维新       | 1
夏颖        | 2
张三        | 1
李四        | 1
简要选       | 0

3. 查找2022年后做过检查的患者

sql 复制代码
SELECT p.patientName 
FROM patient p
WHERE EXISTS (
    SELECT 1 
    FROM prescription 
    WHERE patientID = p.patientID 
      AND examDate > '2022-12-31'
);

输出

sql 复制代码
patientName
夏颖
张三

4. 查找最近3年内做过检查的患者

sql 复制代码
SELECT p.patientName 
FROM patient p
WHERE EXISTS (
    SELECT 1 
    FROM prescription 
    WHERE patientID = p.patientID 
      AND examDate >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR)
);

5. 计算患者年龄并筛选30-40岁之间的患者

sql 复制代码
SELECT patientName, 
       TIMESTAMPDIFF(YEAR, birthDate, CURDATE()) AS age
FROM patient
HAVING age BETWEEN 30 AND 40;

输出

sql 复制代码
patientName | age
姚维新       | 33
夏颖        | 38
简要选       | 43

6. 显示每个检查项目的使用次数

sql 复制代码
SELECT ci.checkItemName, 
       COUNT(pr.prescriptionID) AS usage_count
FROM checkitem ci
LEFT JOIN prescription pr ON ci.checkItemID = pr.checkItemID
GROUP BY ci.checkItemID;

输出

sql 复制代码
checkItemName | usage_count
血常规        | 5
尿常规        | 0
心电图        | 0

四、关键问题与优化建议

  1. 年龄计算的准确性

    • 使用TIMESTAMPDIFF(YEAR, birthDate, CURDATE())替代简单年份差,避免忽略月份和日期。

    • 示例:TIMESTAMPDIFF(YEAR, '1990-05-15', '2023-10-01') 精确计算为33岁。

  2. 子查询性能优化

    • 避免在WHERE子句中对字段使用函数(如YEAR(examDate)),改用范围查询:

      sql 复制代码
      WHERE examDate BETWEEN '2023-01-01' AND '2023-12-31'
相关推荐
꧁༺朝花夕逝༻꧂10 分钟前
MySQL--数据备份
数据库·mysql
快来卷java2 小时前
JVM虚拟机篇(三):JVM运行时数据区与方法区详解
java·jvm·mysql
共享家95272 小时前
Linux常用命令详解:从基础到进阶
linux·服务器·数据库
我是个假程序员6 小时前
sql server数据库可疑修复
数据库
极限实验室8 小时前
如何使用 Nginx 代理 Easysearch 服务
数据库·nginx
whn19778 小时前
selectdb修改表副本
数据库
TDengine (老段)8 小时前
TDengine 中的视图
数据库·物联网·oracle·时序数据库·tdengine·iotdb
Kyrie_Li9 小时前
Redis-Sentinel(哨兵模式)
数据库·redis·sentinel
计算机毕设定制辅导-无忧学长10 小时前
TDengine 数据写入优化:协议选择与批量操作(一)
网络·数据库·tdengine
Mr.洛 白10 小时前
OpenEuler/CentOS一键部署OpenGauss数据库教程(脚本+视频)
数据库·opengauss·gaussdb·国产数据库安装·安装脚本