4. 患者主索引与去重工程

在临床研究队列构建中,患者主索引(Enterprise Master Patient Index,EMPI)是连接多源异构数据的枢纽。同一名患者可能在HIS、LIS、PACS、电子病历、随访系统中拥有不同的内部ID、门诊号、住院号、医保号或身份证号。若不能将这些标识正确映射到唯一患者主键,后续的纳排、随访和统计分析都会出现重复计数或错误关联。本节围绕跨系统标识映射、重复记录识别以及ROW_NUMBER窗口函数在患者级去重中的应用展开。

一、跨系统患者标识映射的基本结构

跨系统标识映射的核心是建立“源系统标识—患者主索引”的对应关系。常见做法是维护一张患者标识交叉映射表,字段包括:empi_id(患者主索引)、source_system(来源系统)、source_patient_id(源系统患者ID)、id_type(标识类型,如门诊号、住院号、身份证号、医保号)、match_rule(匹配规则)、confidence(置信度)以及effective_time(生效时间)。

映射策略通常分为确定性匹配与概率匹配。确定性匹配依赖强标识,如身份证号、医保号完全一致;概率匹配则结合姓名、性别、出生日期、手机号等字段计算相似度。在SQL工程中,确定性匹配优先执行,概率匹配作为补充,并保留人工复核入口。

跨系统患者标识映射与患者级去重数据流 HIS 系统 门诊号 / 住院号 姓名 / 性别 / 出生日期 身份证号 / 医保号 source_system = 'HIS' LIS 系统 检验申请号 姓名 / 性别 / 年龄 就诊卡号 source_system = 'LIS' 随访系统 随访编号 手机号 / 姓名 出生日期 source_system = 'FU' 患者标识交叉映射表 empi_id source_system source_patient_id id_type match_rule confidence effective_time 确定性匹配优先,概率匹配补充 患者级去重(ROW_NUMBER) PARTITION BY empi_id 或 身份证号 ORDER BY 数据完整度 DESC 更新时间 DESC ROW_NUMBER() rn = 1 保留,rn > 1 标记重复 去重判断逻辑 同一患者多条记录 → 按优先级排序 保留 rn=1,其余进入复核队列 唯一患者主索引表(empi_id 唯一) 注:图中字段与规则为教学示例,实际项目需结合机构数据字典与伦理要求调整

二、重复记录识别:从规则到可执行SQL

重复记录识别需要先定义“重复”的判定标准。在临床数据中,常见重复场景包括:同一患者因多次就诊产生多条记录、同一患者在不同系统中姓名写法不同、身份证号缺失导致仅靠姓名和出生日期匹配等。识别过程通常分三步:

  1. 强标识精确匹配:身份证号或医保号完全一致,直接判定为同一患者。
  2. 组合字段匹配:姓名+性别+出生日期+手机号组合一致,置信度较高。
  3. 模糊匹配:姓名编辑距离、出生日期允许±1天误差、手机号后四位一致等,作为候选重复。

以下示例展示如何用SQL标记候选重复记录。假设已有patient_raw表,包含source_system、source_patient_id、name、gender、birth_date、id_card、phone、update_time等字段。

-- 步骤1:生成标准化匹配键
WITH normalized AS (
  SELECT
    source_system,
    source_patient_id,
    name,
    gender,
    birth_date,
    id_card,
    phone,
    update_time,
    -- 强标识键:身份证号优先
    COALESCE(NULLIF(TRIM(id_card), ''), 
             CONCAT(TRIM(name), '|', gender, '|', birth_date)
    ) AS match_key
  FROM patient_raw
),
-- 步骤2:按匹配键分组,计算组内记录数和排序
ranked AS (
  SELECT
    *,
    COUNT(*) OVER (PARTITION BY match_key) AS grp_cnt,
    ROW_NUMBER() OVER (
      PARTITION BY match_key
      ORDER BY 
        CASE WHEN id_card IS NOT NULL AND TRIM(id_card) <> '' THEN 0 ELSE 1 END,
        update_time DESC
    ) AS rn
  FROM normalized
)
-- 步骤3:输出去重结果与重复标记
SELECT
  match_key,
  source_system,
  source_patient_id,
  name,
  gender,
  birth_date,
  id_card,
  phone,
  grp_cnt,
  rn,
  CASE WHEN rn = 1 THEN 'KEEP' ELSE 'DUPLICATE' END AS dedup_flag
FROM ranked
ORDER BY match_key, rn;

上述查询中,PARTITION BY match_key将同一匹配键的记录归为一组,ROW_NUMBER()按身份证号完整度和更新时间排序,rn = 1的记录作为保留记录,其余标记为重复。若grp_cnt > 1,说明该匹配键下存在多条记录,需要进一步人工复核或按规则合并。

三、ROW_NUMBER与窗口函数在患者级去重中的工程要点

ROW_NUMBER是患者级去重最常用的窗口函数,但工程中需注意以下要点:

  • 排序字段的选择:排序字段直接决定保留哪条记录。常见优先级为:身份证号非空 > 数据完整度高 > 更新时间新 > 来源系统权威性高。排序字段应写入文档,避免不同批次结果不一致。
  • 分区键的粒度:分区键过粗会导致不同患者被误合并,过细则无法识别重复。建议先用强标识分区,再用组合字段分区,最后用模糊匹配补充。
  • NULL值处理:身份证号、手机号等字段可能为空,PARTITION BY中NULL会被视为同一组,需用COALESCE或NULLIF处理,避免大量空值记录被错误归并。
  • 可追溯性:去重结果应保留原始记录ID、匹配键、排序序号和去重标记,便于审计和回溯。
实践提示:在临床研究队列中,患者级去重不是一次性操作。随着新数据接入,需定期重新执行去重流程,并将新产生的重复记录与已有主索引进行比对。建议将去重逻辑封装为视图或存储过程,配合调度任务按日或按周运行。

四、从去重结果到患者主索引

去重完成后,需要将保留记录写入患者主索引表,并建立与各源系统的映射关系。典型的主索引表包含:empi_id(自增或UUID)、id_card、name、gender、birth_date、phone、create_time、update_time、status(active/merged/inactive)。同时,将每条源记录与empi_id的对应关系写入交叉映射表,形成“一患者多标识”的结构。

对于被标记为重复的记录,不应直接删除,而应将其empi_id指向保留记录的empi_id,并在映射表中记录合并关系。这样既保证了患者级唯一性,又保留了数据来源的可追溯性。在后续队列构建中,所有查询均以empi_id为患者主键,避免重复计数。

注意:患者主索引涉及敏感个人信息,去重过程中使用的姓名、身份证号、手机号等字段应遵循机构伦理与数据安全规范。在开发测试环境中,建议使用脱敏或模拟数据,避免真实患者信息泄露。

综上,跨系统患者标识映射、重复记录识别与ROW_NUMBER去重是患者主索引工程的三个核心环节。映射表解决“谁是谁”的问题,重复识别解决“哪些是同一个人”的问题,窗口函数解决“保留哪一条”的问题。三者配合,才能为后续临床研究队列提供干净、唯一、可追溯的患者级数据基础。