3. SQL查询基础回顾
在医疗数据查询中,最常用的四类SQL子句几乎覆盖了日常取数的绝大多数场景:SELECT决定“取哪些列”,WHERE决定“取哪些行”,ORDER BY决定“结果如何排序”,LIMIT决定“最多返回多少行”。本节以患者列表(patient)与就诊记录(visit)两张典型表为对象,回顾这四类子句的直接应用方式,并说明它们在真实医疗查询中的组合逻辑。
一、SELECT:明确输出字段,避免 SELECT *
患者列表查询通常需要患者标识、姓名、性别、出生日期、联系电话等字段。假设患者表结构为:patient(patient_id, name, gender, birth_date, phone, id_card, create_time)。查询在院患者基本信息可写为:
SELECT patient_id, name, gender, birth_date, phone
FROM patient;
在工程实践中应尽量避免 SELECT *。原因有三:一是医疗表常包含身份证号、住址等敏感字段,全列返回会扩大数据暴露面;二是宽表返回大量无关列会增加网络传输与内存开销;三是显式列名能让下游使用方清楚知道结果集结构。若确实需要全部字段,也应显式列出,便于审计。
SELECT还支持列别名与简单表达式。例如计算患者年龄(以当前日期为参照):
SELECT patient_id,
name,
TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age
FROM patient;
这里 AS age 为结果列命名,方便后续在报表或程序中使用。注意不同数据库的日期函数存在差异,MySQL使用TIMESTAMPDIFF,PostgreSQL可用AGE或DATE_PART,实际项目中应统一到目标数据库方言。
二、WHERE:用条件缩小结果集
WHERE用于过滤行,是医疗查询中使用频率最高的子句。常见条件包括等值判断、范围判断、集合判断与空值判断。例如查询2024年1月1日之后建档的女性患者:
SELECT patient_id, name, gender, birth_date
FROM patient
WHERE gender = 'F'
AND create_time >= '2024-01-01';
在就诊记录表visit(visit_id, patient_id, visit_date, dept_id, doctor_id, diagnosis, fee)中,查询某科室在指定时间段内的就诊记录:
SELECT visit_id, patient_id, visit_date, diagnosis, fee
FROM visit
WHERE dept_id = 101
AND visit_date BETWEEN '2024-03-01' AND '2024-03-31';
需要注意几个易错点。第一,字符串与日期常量要用单引号包裹,数值型字段不加引号。第二,BETWEEN ... AND ... 是闭区间,若visit_date含时间部分,需明确边界是否包含当天末尾时刻。第三,判断空值必须用 IS NULL 或 IS NOT NULL,不能用 = NULL,因为NULL参与比较的结果是未知。第四,IN 适合枚举多个科室或诊断编码,LIKE 适合姓名或诊断名称的模糊匹配,但前导通配符 LIKE '%xx' 通常无法使用索引,应谨慎使用。
三、ORDER BY:让结果可预期
ORDER BY用于对结果排序,默认升序ASC,降序需显式写DESC。患者列表常按建档时间倒序,让最新患者排在前面:
SELECT patient_id, name, create_time
FROM patient
ORDER BY create_time DESC;
就诊记录常按就诊日期倒序,同一天再按费用降序:
SELECT visit_id, patient_id, visit_date, fee
FROM visit
ORDER BY visit_date DESC, fee DESC;
多列排序时,数据库先按第一列排序,第一列相同再按第二列排序。排序字段应尽量选择有索引的列,否则大数据量下会产生额外排序开销。此外,若排序列存在NULL,不同数据库对NULL的排序位置默认不同,MySQL中NULL最小,PostgreSQL中NULL最大,跨库迁移时需显式处理。
四、LIMIT:控制返回行数
LIMIT用于限制返回行数,常用于分页与快速预览。查询最近10条就诊记录:
SELECT visit_id, patient_id, visit_date, diagnosis
FROM visit
ORDER BY visit_date DESC
LIMIT 10;
分页查询可写成 LIMIT 20 OFFSET 40,表示跳过前40行取20行,即第3页(每页20条)。需要强调的是,LIMIT必须与ORDER BY配合才有稳定语义。若不加排序,数据库返回的行顺序不保证,分页结果可能重复或遗漏。在医疗场景中,患者列表分页、就诊记录分页都应固定排序键,例如 ORDER BY visit_date DESC, visit_id DESC,用唯一列作为最后排序键消除并列歧义。
五、四类子句的组合执行顺序
一条完整查询中,逻辑执行顺序为:FROM → WHERE → SELECT → ORDER BY → LIMIT。WHERE在分组与排序之前过滤行,ORDER BY在SELECT之后对结果排序,LIMIT最后截断。理解这一顺序有助于判断条件应写在哪一层。例如“查询费用最高的前5条就诊记录”,应先按fee降序排序,再取前5条,而不能在WHERE中写 fee > 某值 来近似替代,因为阈值未知。
六、组合应用示例与结果判读
下面给出一个贴近实际工作的组合查询:查询2024年3月内科(dept_id=101)就诊记录中费用最高的前5条,输出就诊号、患者号、就诊日期、诊断与费用。
SELECT visit_id, patient_id, visit_date, diagnosis, fee
FROM visit
WHERE dept_id = 101
AND visit_date BETWEEN '2024-03-01' AND '2024-03-31'
ORDER BY fee DESC, visit_id DESC
LIMIT 5;
结果判读时关注三点:第一,返回行数是否不超过5;第二,fee是否严格降序;第三,若存在费用相同的记录,visit_id DESC作为第二排序键保证顺序稳定。若查询结果为空,应依次检查WHERE条件中的科室编号、日期范围与数据实际值是否匹配,而不是直接怀疑SQL语法。
name LIKE '张%' 这类前缀匹配,可借助索引提升效率;若必须使用 %张%,应评估数据量与响应时间,必要时改用全文检索或搜索引擎方案。掌握SELECT、WHERE、ORDER BY、LIMIT这四类子句的组合方式,是后续学习多表连接、聚合统计与窗口函数的基础。在患者列表与就诊记录这两类高频查询中,先把字段选准、条件写清、排序定稳、行数控好,就能覆盖大量日常取数需求。