Chuyển đến nội dung chính

Bài 7: CONDITION_OCCURRENCE — Chẩn đoán & Bệnh lý

Ghi nhận chẩn đoán, triệu chứng, dấu hiệu bệnh lý, condition_concept_id vs source_value, condition_status (admitting/primary/secondary), liên kết với Visit và Provider, phân biệt với OBSERVATION table.

🏗️ Kiến trúc — Bài 7 CONDITION_OCCURRENCE Chẩn đoán & Bệnh lý OMOP CDM 5.4 cho Người mới — Hiểu từ A đến Z Phần 3: Sự kiện lâm sàng chính xdev.asia

Quy trình mapping ICD-10 → SNOMED trong CONDITION_OCCURRENCE

Giới thiệu

CONDITION_OCCURRENCE ghi nhận mọi chẩn đoán, triệu chứng, và dấu hiệu bệnh lý mà bác sĩ ghi nhận cho bệnh nhân. Đây thường là bảng được phân tích nhiều nhất trong OMOP CDM — vì nghiên cứu y tế thường bắt đầu từ câu hỏi: "Ai bị bệnh gì?"


1. Cấu trúc bảng

CộtKiểuBắt buộcMô tả
condition_occurrence_idINTEGER✅ PKID duy nhất
person_idINTEGER✅ FKBệnh nhân
condition_concept_idINTEGER✅Standard Concept (SNOMED)
condition_start_dateDATE✅Ngày bắt đầu chẩn đoán
condition_start_datetimeDATETIMENgày giờ
condition_end_dateDATENgày hết chẩn đoán
condition_end_datetimeDATETIMENgày giờ kết thúc
condition_type_concept_idINTEGER✅Nguồn dữ liệu
condition_status_concept_idINTEGERTrạng thái (Primary, Admitting...)
stop_reasonVARCHAR(20)Lý do ngưng chẩn đoán
provider_idINTEGERFKBác sĩ chẩn đoán
visit_occurrence_idINTEGERFKVisit liên quan
visit_detail_idINTEGERFKVisit detail (khoa nào)
condition_source_valueVARCHAR(50)Mã gốc (VD: "E11")
condition_source_concept_idINTEGERConcept gốc
condition_status_source_valueVARCHAR(50)Status gốc

2. Lưu gì vào CONDITION_OCCURRENCE?

2.1. NÊN lưu

LoạiVí dụVocabulary
Chẩn đoán bệnhTiểu đường type 2, Viêm phổiSNOMED CT
Triệu chứngSốt, Đau bụng, HoSNOMED CT
Dấu hiệu lâm sàngPhù chân, Vàng daSNOMED CT
Chẩn đoán phân biệtNghi ngờ lao phổiSNOMED CT

2.2. KHÔNG NÊN lưu (lưu ở bảng khác)

LoạiBảng đíchLý do
"Tiền sử tiểu đường"OBSERVATIONDomain = Observation
"Không bị dị ứng"OBSERVATIONAbsence → Observation
"BMI = 28"MEASUREMENTDomain = Measurement
Tác dụng phụ thuốcCONDITION + DRUG_EXPOSURECondition cho ADR, Drug cho thuốc gây ra

3. condition_status_concept_id — Trạng thái chẩn đoán

Concept IDStatusÝ nghĩa
32902Primary diagnosisChẩn đoán chính
32908Secondary diagnosisChẩn đoán phụ
32903Admitting diagnosisChẩn đoán lúc nhập viện
32904Discharge diagnosisChẩn đoán lúc xuất viện
32906Provisional diagnosisChẩn đoán tạm thời
32907Confirmed diagnosisChẩn đoán xác nhận
-- Ví dụ: BN nhập viện
-- Chẩn đoán nhập viện: Nghi lao phổi (provisional)
INSERT INTO condition_occurrence VALUES (
    70001, 100001, 255848,       -- SNOMED: Pneumonia
    '2024-06-10', NULL,
    '2024-06-20', NULL,
    32817,                        -- EHR
    32903,                        -- Admitting diagnosis
    NULL, 5001, 50001, NULL,
    'J18.9', 0,                   -- ICD-10: Pneumonia, unspecified
    'admitting'
);

-- Chẩn đoán xuất viện: Viêm phổi do phế cầu (confirmed)
INSERT INTO condition_occurrence VALUES (
    70002, 100001, 257315,       -- SNOMED: Pneumococcal pneumonia
    '2024-06-10', NULL,
    '2024-06-20', NULL,
    32817,                        -- EHR
    32904,                        -- Discharge diagnosis
    NULL, 5001, 50001, NULL,
    'J13', 0,                     -- ICD-10
    'discharge'
);

4. ETL cho dữ liệu ICD-10 Việt Nam

4.1. Quy trình mapping

  HIS: ma_benh = 'E11.65'  (ICD-10-CM)
       ten_benh = 'ĐTĐ type 2 có biến chứng mạch máu ngoại vi'
       │
       │ Bước 1: Tìm source concept
       ↓
  SOURCE CONCEPT: concept_id = 45591837
       vocabulary_id = ICD10CM
       concept_code = 'E11.65'
       │
       │ Bước 2: Tìm Standard Concept (Maps to)
       ↓
  STANDARD CONCEPT: concept_id = 201826
       vocabulary_id = SNOMED
       concept_name = 'Type 2 diabetes mellitus'
       domain_id = 'Condition'
-- SQL ETL
SELECT
    ROW_NUMBER() OVER() AS condition_occurrence_id,
    pm.person_id,
    COALESCE(cr.concept_id_2, 0) AS condition_concept_id,
    cd.ngay_chandoan AS condition_start_date,
    NULL AS condition_end_date,
    32817 AS condition_type_concept_id,
    CASE cd.loai_chandoan
        WHEN 'CHINH' THEN 32902   -- Primary
        WHEN 'PHU'   THEN 32908   -- Secondary
        ELSE 0
    END AS condition_status_concept_id,
    cd.ma_icd10 AS condition_source_value,
    COALESCE(c_source.concept_id, 0) AS condition_source_concept_id
FROM chandoan_his cd
JOIN person_mapping pm ON cd.ma_bn = pm.source_id
LEFT JOIN concept c_source
    ON cd.ma_icd10 = c_source.concept_code
    AND c_source.vocabulary_id = 'ICD10CM'
LEFT JOIN concept_relationship cr
    ON c_source.concept_id = cr.concept_id_1
    AND cr.relationship_id = 'Maps to'
LEFT JOIN concept c_std
    ON cr.concept_id_2 = c_std.concept_id
    AND c_std.standard_concept = 'S';

4.2. Xử lý dữ liệu đặc thù VN

Vấn đềGiải pháp
ICD-10-VN khác ICD-10-CMMapping qua SOURCE_TO_CONCEPT_MAP
Mã nội bộ BVUsagi mapping tool
Thiếu ngày kết thúccondition_end_date = NULL (hợp lệ)
1 ICD map nhiều SNOMEDChọn concept phù hợp nhất

5. Phân biệt CONDITION vs OBSERVATION

Tiêu chíCONDITION_OCCURRENCEOBSERVATION
Nội dungBệnh hiện tại / đang điều trịTiền sử, lối sống, ghi nhận
Ví dụ"Tiểu đường type 2""Tiền sử tiểu đường gia đình"
DomainConditionObservation
Standard VocabSNOMED CTSNOMED CT
Khi nào?Bệnh đang hoạt độngGhi nhận thông tin

Quy tắc: Luôn kiểm tra domain_id của Standard Concept trên Athena. Nếu domain = "Observation", lưu vào OBSERVATION dù nguồn là ICD-10.


6. SQL phân tích phổ biến

-- Top 10 chẩn đoán phổ biến nhất
SELECT
    c.concept_name AS condition_name,
    COUNT(DISTINCT co.person_id) AS patient_count,
    COUNT(*) AS record_count
FROM condition_occurrence co
JOIN concept c ON co.condition_concept_id = c.concept_id
WHERE co.condition_concept_id != 0
GROUP BY c.concept_name
ORDER BY patient_count DESC
LIMIT 10;

-- Tỉ lệ mắc bệnh theo giới tính
SELECT
    g.concept_name AS gender,
    c.concept_name AS condition_name,
    COUNT(DISTINCT co.person_id) AS patients
FROM condition_occurrence co
JOIN person p ON co.person_id = p.person_id
JOIN concept g ON p.gender_concept_id = g.concept_id
JOIN concept c ON co.condition_concept_id = c.concept_id
WHERE co.condition_concept_id = 201826  -- Type 2 DM
GROUP BY g.concept_name, c.concept_name;

-- Comorbidity: BN tiểu đường có tăng huyết áp?
SELECT
    COUNT(DISTINCT co_dm.person_id) AS dm_patients,
    COUNT(DISTINCT co_ht.person_id) AS dm_with_hypertension,
    ROUND(
        COUNT(DISTINCT co_ht.person_id) * 100.0 /
        NULLIF(COUNT(DISTINCT co_dm.person_id), 0), 1
    ) AS comorbidity_pct
FROM condition_occurrence co_dm
LEFT JOIN condition_occurrence co_ht
    ON co_dm.person_id = co_ht.person_id
    AND co_ht.condition_concept_id IN (
        SELECT descendant_concept_id
        FROM concept_ancestor
        WHERE ancestor_concept_id = 320128  -- Essential hypertension
    )
WHERE co_dm.condition_concept_id IN (
    SELECT descendant_concept_id
    FROM concept_ancestor
    WHERE ancestor_concept_id = 201826  -- Type 2 DM
);

Tổng kết

  1. CONDITION_OCCURRENCE = chẩn đoán, triệu chứng, dấu hiệu bệnh lý
  2. condition_concept_id dùng Standard Concept (SNOMED CT)
  3. condition_status: Primary, Secondary, Admitting, Discharge
  4. Bộ ba cột: concept_id / source_value / source_concept_id
  5. Phân biệt CONDITION (bệnh hiện tại) vs OBSERVATION (tiền sử, ghi nhận)
  6. ETL VN: ICD-10-VN → Source Concept → Maps to → Standard SNOMED

Bài tiếp theo: DRUG_EXPOSURE — cách OMOP CDM ghi nhận thuốc, kê đơn, và vaccine.


Tài liệu tham khảo