一、数据库表结构设计
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
四、关键问题与优化建议
-
年龄计算的准确性
-
使用
TIMESTAMPDIFF(YEAR, birthDate, CURDATE())
替代简单年份差,避免忽略月份和日期。 -
示例:
TIMESTAMPDIFF(YEAR, '1990-05-15', '2023-10-01')
精确计算为33岁。
-
-
子查询性能优化
-
避免在
WHERE
子句中对字段使用函数(如YEAR(examDate)
),改用范围查询:sqlWHERE examDate BETWEEN '2023-01-01' AND '2023-12-31'
-