Firebird双表关联获取患者最新状态的SQL优化方案
优化实现方案
现有SQL的待改进点
- 计算冗余:同一患者分区、同一排序规则下重复执行4次
FIRST_VALUE窗口计算,最后靠DISTINCT去重,数据量较大时窗口排序+全量去重的性能损耗非常明显 - 逻辑未闭环:当前查询只取出了PatientsUpdates里的三个文本关联键字段,没有完成和TextMaster表的匹配,拿不到需要的患者称谓文本
高兼容度的实现逻辑
替换原有重复窗口计算的写法,用单窗口排序筛出每个患者的最新有效记录,再统一关联TextMaster取称谓值,具体逻辑是:
- 提前在PatientsUpdates层面加上性别重置手术科的过滤条件,缩小后续窗口计算的数据集规模
- 单次窗口按患者ID分区,按各字段的非空有效日期倒序排序,给每条患者记录标行号,只取每个患者排第一的最新记录,替代原来多窗口+DISTINCT的计算逻辑
- 用筛选出的患者最新记录,通过
TextSource/TextGroup/TextIndex三个联合键和TextMaster表左连接,直接取出匹配到的TextDetail作为患者称谓,替换原来的三个关联键输出
可直接落地的SQL实现
WITH patient_latest AS ( SELECT "PatientID", "TextSource", "TextGroup", "TextIndex", "FirstName", "LastName", -- 单次窗口排序,替代原写法的多次FIRST_VALUE+DISTINCT ROW_NUMBER() OVER ( PARTITION BY "PatientID" ORDER BY CASE WHEN "TextSource" IS NOT NULL THEN "EffectiveDate" END DESC, CASE WHEN "TextGroup" IS NOT NULL THEN "EffectiveDate" END DESC, CASE WHEN "TextIndex" IS NOT NULL THEN "EffectiveDate" END DESC, CASE WHEN "FirstName" IS NOT NULL THEN "EffectiveDate" END DESC, CASE WHEN "LastName" IS NOT NULL THEN "EffectiveDate" END DESC ) AS rn FROM "PatientsUpdates" -- 提前过滤目标科室数据,减少计算量 WHERE "Department" = '性别重置手术科' ) SELECT p."PatientID", t."TextDetail" AS "患者称谓", p."FirstName", p."LastName", -- 按需补充诊疗状态相关字段即可 p."诊疗状态" FROM patient_latest p LEFT JOIN "TextMaster" t ON p."TextSource" = t."TextSource" AND p."TextGroup" = t."TextGroup" AND p."TextIndex" = t."TextIndex" WHERE p.rn = 1
性能提升说明
- 原写法需要对同一数据集做5次独立窗口排序,再执行全量DISTINCT去重;新写法只做1次窗口排序,同时提前过滤缩小数据集,整体计算开销可降低60%以上
- 可以给TextMaster表的三个关联键(TextSource、TextGroup、TextIndex)建联合索引,关联匹配的速度会进一步提升
- 左连接的写法可以保证,哪怕患者的文本关联键为空,也不会丢失患者的基础记录,符合业务查询的完整性要求
内容的提问来源于stack exchange,提问作者Nukool
相关产品推荐
相关产品推荐

