数据库——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'
相关推荐
lzhdim35 分钟前
SQL 入门 12:SQL 视图:创建、修改与可更新视图
java·大数据·服务器·数据库·sql
2301_795099741 小时前
让 CSS Grid 自适应容器尺寸的动态布局方案
jvm·数据库·python
FQNmxDG4S1 小时前
Maven依赖管理:版本冲突解决与生命周期控制
java·数据库·maven
热爱运维的小七2 小时前
告别内存溢出:ActiveMQ 性能诊断与全流程优化
数据库·it运维·activemq·devops
@小柯555m2 小时前
MySql(高级操作符--操作符混合运用)
数据库·sql·mysql
CDN3602 小时前
排查实录:网站偶发502/504错误?360CDN回源超时配置与日志分析技巧
前端·数据库
bzmK1DTbd2 小时前
JDBC编程规范:PreparedStatement与事务管理
数据库·python·eclipse
卧室小白2 小时前
Redis-哨兵模式
数据库·redis·缓存
GottdesKrieges2 小时前
OceanBase恢复常见问题
java·数据库·oceanbase
卧室小白3 小时前
redis-配置
数据库·redis·缓存