数据库——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'
相关推荐
盖世英雄酱5813624 分钟前
事务报错,为何数据还是插入成功了❓
java·数据库·后端
钢铁男儿39 分钟前
C# 枚举器和迭代器(常见迭代器模式)
数据库·c#·迭代器模式
哥哥还在IT中1 小时前
脚本统计MongoDB集合表数据量
数据库·mongodb
爱敲代码的TOM2 小时前
手撕Redis源码1-数据结构实现
数据库·redis·缓存
孫治AllenSun2 小时前
【Mysql】联合索引生效分析案例
java·数据库·mysql
蓝黑20202 小时前
MySQL的case
数据库·mysql
书唐瑞2 小时前
Percona pt-archiver 出现数据不对等
java·服务器·数据库
ALLSectorSorft2 小时前
相亲小程序个人资料管理系统模块搭建
服务器·网络·数据库·python·sql
CHEN5_022 小时前
【Java面试题】缓存穿透
java·开发语言·数据库·redis·缓存
卍郝凝卍2 小时前
云服务器数据库
运维·服务器·数据库