如何从Snomed Postgres SQL数据库提取概念的亲属关系
解决SNOMED CT数据库中查询亲属概念的问题
我来帮你梳理下如何在PostgreSQL的SNOMED CT库中查询特定概念的父、祖父、子、孙概念——核心是利用SNOMED的Is a层级关系(这是构建整个术语体系的基础),下面一步步来:
先明确核心表关联逻辑
SNOMED CT导入后,你需要关注两个核心表:
concept:存储所有概念的基本信息,concept_id是唯一标识,active字段标记该概念是否处于有效状态。relationship:存储概念间的各种关系,其中**type_id = 116680003**对应SNOMED标准的「Is a」(从属)关系,这是我们查询层级亲属的关键。
在「Is a」关系中:
source_id是子概念的ID,destination_id是父概念的ID(比如「肺癌(93880001)」Is a「恶性肺肿瘤」,所以source_id=93880001,destination_id=父概念ID)
1. 查询直接父概念(上位词)
要获取肺癌的直接父概念,我们需要关联relationship和concept表,过滤有效关系和概念:
SELECT c.concept_id AS parent_concept_id, c.fsn AS parent_concept_name FROM relationship r JOIN concept c ON r.destination_id = c.concept_id WHERE r.source_id = 93880001 -- 你的目标概念ID(肺癌) AND r.type_id = 116680003 -- Is a关系 AND r.active = true -- 只取有效关系 AND c.active = true; -- 只取有效概念
2. 查询祖父概念(父概念的父)
可以用递归CTE来实现多层级向上查询,这样不仅能查祖父,还能扩展到任意层级的祖先:
WITH RECURSIVE ancestor AS ( -- 初始层:直接父概念 SELECT r.destination_id AS ancestor_id, 1 AS depth FROM relationship r WHERE r.source_id = 93880001 AND r.type_id = 116680003 AND r.active = true UNION ALL -- 递归层:向上找父的父 SELECT r.destination_id AS ancestor_id, a.depth + 1 AS depth FROM relationship r JOIN ancestor a ON r.source_id = a.ancestor_id WHERE r.type_id = 116680003 AND r.active = true ) SELECT c.concept_id AS grandparent_id, c.fsn AS grandparent_name FROM ancestor a JOIN concept c ON a.ancestor_id = c.concept_id WHERE a.depth = 2 -- depth=2就是祖父,depth=3是曾祖父,以此类推 AND c.active = true;
3. 查询直接子概念(下位词)
子概念的查询逻辑和父概念相反:在「Is a」关系中,子概念的source_id是自己,destination_id是目标概念(肺癌):
SELECT c.concept_id AS child_concept_id, c.fsn AS child_concept_name FROM relationship r JOIN concept c ON r.source_id = c.concept_id WHERE r.destination_id = 93880001 -- 目标概念ID(肺癌) AND r.type_id = 116680003 AND r.active = true AND c.active = true;
4. 查询孙概念(子概念的子)
同样用递归CTE向下查询:
WITH RECURSIVE descendant AS ( -- 初始层:直接子概念 SELECT r.source_id AS descendant_id, 1 AS depth FROM relationship r WHERE r.destination_id = 93880001 AND r.type_id = 116680003 AND r.active = true UNION ALL -- 递归层:向下找子的子 SELECT r.source_id AS descendant_id, d.depth + 1 AS depth FROM relationship r JOIN descendant d ON r.destination_id = d.descendant_id WHERE r.type_id = 116680003 AND r.active = true ) SELECT c.concept_id AS grandchild_id, c.fsn AS grandchild_name FROM descendant d JOIN concept c ON d.descendant_id = c.concept_id WHERE d.depth = 2 -- depth=2是孙概念,depth=3是曾孙,以此类推 AND c.active = true;
额外提示
- 如果你需要查询所有祖先/后代(不限层级),只需要去掉CTE中的
depth过滤条件即可。 - 确保始终过滤
active = true的记录,SNOMED CT包含很多历史废弃的概念和关系,避免查询到无效数据。 fsn字段是「 Fully Specified Name」(完全限定名),是SNOMED概念的标准唯一名称,如果你需要更友好的名称,也可以关联description表并过滤type_id = 900000000000003001(Preferred Term)来获取常用名。
内容的提问来源于stack exchange,提问作者Parvez Khan
相关产品推荐
相关产品推荐

