@xdev-asia/xdev-knowledge-mcp 1.0.55 → 1.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/01-phan-1-tong-quan-nen-tang/lessons/bai-1-omop-cdm-la-gi-tai-sao-can-chuan-hoa-du-lieu-y-te.md +339 -0
  2. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/01-phan-1-tong-quan-nen-tang/lessons/bai-2-kien-truc-tong-the-omop-cdm-5-4-nhom-bang-nguyen-ly-thiet-ke.md +440 -0
  3. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/01-phan-1-tong-quan-nen-tang/lessons/bai-3-hieu-concept-trai-tim-cua-omop-cdm.md +441 -0
  4. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/02-phan-2-person-visit-nen-tang/lessons/bai-4-bang-person-quan-ly-danh-tinh-benh-nhan.md +323 -0
  5. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/02-phan-2-person-visit-nen-tang/lessons/bai-5-observation-period-khoang-thoi-gian-theo-doi-benh-nhan.md +308 -0
  6. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/02-phan-2-person-visit-nen-tang/lessons/bai-6-visit-occurrence-visit-detail-luot-kham-chi-tiet.md +353 -0
  7. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/03-phan-3-su-kien-lam-sang-chinh/lessons/bai-10-measurement-xet-nghiem-do-luong.md +409 -0
  8. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/03-phan-3-su-kien-lam-sang-chinh/lessons/bai-7-condition-occurrence-chan-doan-benh-ly.md +285 -0
  9. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/03-phan-3-su-kien-lam-sang-chinh/lessons/bai-8-drug-exposure-thuoc-dieu-tri.md +354 -0
  10. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/03-phan-3-su-kien-lam-sang-chinh/lessons/bai-9-procedure-occurrence-thu-thuat-phau-thuat.md +291 -0
  11. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/04-phan-4-bang-lam-sang-mo-rong/lessons/bai-11-observation-su-kien-lam-sang-tong-hop.md +289 -0
  12. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/04-phan-4-bang-lam-sang-mo-rong/lessons/bai-12-device-exposure-specimen-note.md +313 -0
  13. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/04-phan-4-bang-lam-sang-mo-rong/lessons/bai-13-death-episode-episode-event.md +346 -0
  14. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/05-phan-5-standardized-vocabularies/lessons/bai-14-concept-vocabulary-nen-tang-tu-dien-chuan.md +298 -0
  15. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/05-phan-5-standardized-vocabularies/lessons/bai-15-concept-relationship-concept-ancestor.md +336 -0
  16. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/05-phan-5-standardized-vocabularies/lessons/bai-16-drug-strength-cac-bang-vocabulary-con-lai.md +295 -0
  17. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/06-phan-6-health-system-economics-derived/lessons/bai-17-location-care-site-provider.md +334 -0
  18. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/06-phan-6-health-system-economics-derived/lessons/bai-18-payer-plan-period-cost.md +343 -0
  19. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/06-phan-6-health-system-economics-derived/lessons/bai-19-condition-era-drug-era-dose-era.md +418 -0
  20. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/chapters/07-phan-7-metadata-cohort-tong-ket/lessons/bai-20-cdm-source-metadata-cohort-tong-ket.md +517 -0
  21. package/content/series/architecture/omop-cdm-5-4-cho-nguoi-moi-bat-dau/index.md +385 -0
  22. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/01-bai-1-gioi-thieu-vyos-va-cai-dat.md +10 -1
  23. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/02-bai-2-cau-hinh-interface-va-ip-co-ban.md +4 -3
  24. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/03-bai-3-nat-source-nat-destination-nat-va-masquerade.md +1 -0
  25. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/04-bai-4-firewall-co-ban-rules-chains-va-groups.md +2 -2
  26. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/05-bai-5-zone-based-firewall.md +2 -2
  27. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/06-bai-6-dhcp-server-dns-forwarding-va-ntp.md +4 -1
  28. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/07-bai-7-vlans-bonding-va-bridge.md +2 -0
  29. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/08-bai-8-static-routing-va-policy-based-routing.md +2 -0
  30. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/09-bai-9-dynamic-routing-ospf.md +2 -0
  31. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/10-bai-10-dynamic-routing-bgp.md +2 -0
  32. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/11-bai-11-vpn-wireguard-va-openvpn.md +2 -0
  33. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/12-bai-12-vpn-ipsec-site-to-site.md +2 -0
  34. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/13-bai-13-high-availability-vrrp-va-conntrack-sync.md +2 -0
  35. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/14-bai-14-wan-load-balancing-qos-va-monitoring.md +2 -0
  36. package/content/series/devsecops/vyos-tu-co-ban-den-nang-cao/chapters/01-vyos-tu-co-ban-den-nang-cao/lessons/15-bai-15-containers-automation-va-production-best-practices.md +2 -0
  37. package/package.json +1 -1
@@ -0,0 +1,409 @@
1
+ ---
2
+ id: 019f1a00-a110-7b01-e001-omopcdm54010
3
+ title: "Bài 10: MEASUREMENT — Xét nghiệm & Đo lường"
4
+ slug: bai-10-measurement-xet-nghiem-do-luong
5
+ description: >-
6
+ Ghi nhận kết quả xét nghiệm, sinh hiệu, đo lường lâm sàng.
7
+ value_as_number / value_as_concept_id, operator_concept_id,
8
+ unit_concept_id, range_low / range_high, LOINC vocabulary,
9
+ measurement_event_id mới CDM 5.4.
10
+ duration_minutes: 65
11
+ is_free: true
12
+ video_url: null
13
+ sort_order: 10
14
+ section_title: "Phần 3: Sự kiện lâm sàng chính"
15
+ course:
16
+ id: 019f1a00-a100-7b01-e001-omopcdm54001
17
+ title: "OMOP CDM 5.4 cho Người mới — Hiểu từ A đến Z"
18
+ slug: omop-cdm-5-4-cho-nguoi-moi-bat-dau
19
+ ---
20
+
21
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 340" style="max-width: 100%; height: auto; border-radius: 12px; margin-bottom: 1.5rem;">
22
+ <defs>
23
+ <linearGradient id="bg-omop10" x1="0%" y1="0%" x2="100%" y2="100%">
24
+ <stop offset="0%" style="stop-color:#0c1222"/>
25
+ <stop offset="100%" style="stop-color:#1e293b"/>
26
+ </linearGradient>
27
+ </defs>
28
+ <rect width="1200" height="340" rx="12" fill="url(#bg-omop10)"/>
29
+ <g>
30
+ <circle cx="670" cy="85" r="20" fill="#818cf8" opacity="0.12"/>
31
+ <circle cx="750" cy="115" r="28" fill="#818cf8" opacity="0.09"/>
32
+ <circle cx="830" cy="95" r="35" fill="#818cf8" opacity="0.06"/>
33
+ <circle cx="920" cy="155" r="22" fill="#818cf8" opacity="0.10"/>
34
+ <line x1="610" y1="165" x2="1100" y2="245" stroke="#818cf8" stroke-width="0.5" opacity="0.1"/>
35
+ </g>
36
+ <rect x="60" y="50" width="4" height="60" rx="2" fill="#818cf8"/>
37
+ <rect x="80" y="50" width="130" height="28" rx="14" fill="#818cf8" opacity="0.15"/>
38
+ <text x="92" y="69" font-family="system-ui,-apple-system,sans-serif" font-size="13" font-weight="600" fill="#818cf8">🏗️ Kiến trúc — Bài 10</text>
39
+ <text x="60" y="140" font-family="system-ui,-apple-system,sans-serif" font-size="34" font-weight="700" fill="#f1f5f9">
40
+ <tspan x="60" dy="0">MEASUREMENT</tspan>
41
+ <tspan x="60" dy="42">Xét nghiệm &amp; Đo lường</tspan>
42
+ </text>
43
+ <text x="60" y="244" font-family="system-ui,-apple-system,sans-serif" font-size="15" fill="#94a3b8" opacity="0.8">OMOP CDM 5.4 cho Người mới — Hiểu từ A đến Z</text>
44
+ <text x="60" y="268" font-family="system-ui,-apple-system,sans-serif" font-size="13" fill="#64748b" opacity="0.6">Phần 3: Sự kiện lâm sàng chính</text>
45
+ <text x="1140" y="320" font-family="system-ui,-apple-system,sans-serif" font-size="12" fill="#475569" text-anchor="end" opacity="0.4">xdev.asia</text>
46
+ </svg>
47
+
48
+ ![Dashboard xét nghiệm và đo lường y tế](/storage/uploads/2026/04/omop-cdm-bai10-measurement-lab.png)
49
+
50
+ ## Giới thiệu
51
+
52
+ **MEASUREMENT** là bảng ghi nhận mọi kết quả xét nghiệm, sinh hiệu, và đo lường lâm sàng — bất kỳ dữ liệu nào có **giá trị đo được** (số hoặc danh mục). Đây là bảng lớn nhất trong hầu hết database OMOP, thường chiếm >50% tổng record vì mỗi lần xét nghiệm tạo nhiều dòng (VD: bảng xét nghiệm máu 20 chỉ số = 20 records).
53
+
54
+ ---
55
+
56
+ ## 1. Cấu trúc bảng
57
+
58
+ | Cột | Kiểu | Bắt buộc | Mô tả |
59
+ |-----|------|----------|-------|
60
+ | `measurement_id` | INTEGER | ✅ PK | ID duy nhất |
61
+ | `person_id` | INTEGER | ✅ FK | Bệnh nhân |
62
+ | `measurement_concept_id` | INTEGER | ✅ | Standard Concept (LOINC) |
63
+ | `measurement_date` | DATE | ✅ | Ngày xét nghiệm |
64
+ | `measurement_datetime` | DATETIME | | Ngày giờ |
65
+ | `measurement_time` | VARCHAR(10) | | Giờ (legacy) |
66
+ | `measurement_type_concept_id` | INTEGER | ✅ | Nguồn dữ liệu |
67
+ | `operator_concept_id` | INTEGER | | Toán tử (<, >, =, <=, >=) |
68
+ | `value_as_number` | FLOAT | | Giá trị số |
69
+ | `value_as_concept_id` | INTEGER | | Giá trị danh mục |
70
+ | `unit_concept_id` | INTEGER | | Đơn vị (UCUM) |
71
+ | `range_low` | FLOAT | | Giới hạn dưới bình thường |
72
+ | `range_high` | FLOAT | | Giới hạn trên bình thường |
73
+ | `provider_id` | INTEGER | FK | Bác sĩ yêu cầu |
74
+ | `visit_occurrence_id` | INTEGER | FK | Visit liên quan |
75
+ | `visit_detail_id` | INTEGER | FK | Visit detail |
76
+ | `measurement_source_value` | VARCHAR(50) | | Mã xét nghiệm gốc |
77
+ | `measurement_source_concept_id` | INTEGER | | Concept gốc |
78
+ | `unit_source_value` | VARCHAR(50) | | Đơn vị gốc |
79
+ | `unit_source_concept_id` | INTEGER | | Concept đơn vị gốc |
80
+ | `value_source_value` | VARCHAR(50) | | Giá trị gốc |
81
+ | `measurement_event_id` | BIGINT | | ⭐ CDM 5.4 mới |
82
+ | `meas_event_field_concept_id` | INTEGER | | ⭐ CDM 5.4 mới |
83
+
84
+ ---
85
+
86
+ ## 2. value_as_number vs value_as_concept_id
87
+
88
+ ### 2.1. Kết quả SỐ → value_as_number
89
+
90
+ ```sql
91
+ -- Glucose máu: 6.5 mmol/L
92
+ INSERT INTO measurement VALUES (
93
+ 110001, 100001, 3004501, -- LOINC: Glucose [Mass/volume] in Blood
94
+ '2024-06-15', NULL, NULL,
95
+ 32817, -- EHR
96
+ 4172703, -- = (equals)
97
+ 6.5, -- value_as_number
98
+ NULL, -- no concept value
99
+ 8753, -- UCUM: mmol/L
100
+ 3.9, 6.1, -- range: 3.9-6.1
101
+ 5001, 50001, NULL,
102
+ 'GLU', 0, 'mmol/L', 0,
103
+ '6.5', NULL, NULL
104
+ );
105
+ ```
106
+
107
+ ### 2.2. Kết quả DANH MỤC → value_as_concept_id
108
+
109
+ ```sql
110
+ -- Xét nghiệm nhóm máu: O
111
+ INSERT INTO measurement VALUES (
112
+ 110002, 100001, 3003694, -- LOINC: ABO group [Type] in Blood
113
+ '2024-06-15', NULL, NULL,
114
+ 32817, -- EHR
115
+ NULL, -- no operator
116
+ NULL, -- no numeric value
117
+ 36308332, -- Concept: Blood group O
118
+ NULL, -- no unit
119
+ NULL, NULL, -- no range
120
+ 5001, 50001, NULL,
121
+ 'BLOOD_TYPE', 0, NULL, 0,
122
+ 'O', NULL, NULL
123
+ );
124
+ ```
125
+
126
+ ### 2.3. Quy tắc chọn
127
+
128
+ | Kết quả | value_as_number | value_as_concept_id |
129
+ |---------|----------------|-------------------|
130
+ | "6.5 mmol/L" | 6.5 | NULL |
131
+ | "Dương tính" | NULL | 4181412 (Positive) |
132
+ | "Âm tính" | NULL | 4132135 (Negative) |
133
+ | "Nhóm máu O" | NULL | 36308332 |
134
+ | "> 100" | 100 | NULL + operator = > |
135
+ | "Bình thường" | NULL | 4069590 (Normal) |
136
+
137
+ ---
138
+
139
+ ## 3. operator_concept_id — Toán tử so sánh
140
+
141
+ Dùng khi kết quả không chính xác (VD: "< 0.5", "> 100").
142
+
143
+ | Concept ID | Toán tử | Ý nghĩa |
144
+ |-----------|---------|---------|
145
+ | 4171756 | < | Thấp hơn |
146
+ | 4171754 | <= | Thấp hơn hoặc bằng |
147
+ | 4172703 | = | Bằng (mặc định) |
148
+ | 4172704 | >= | Cao hơn hoặc bằng |
149
+ | 4172702 | > | Cao hơn |
150
+
151
+ ```sql
152
+ -- Kết quả HBsAg: < 0.05 (dưới ngưỡng phát hiện)
153
+ INSERT INTO measurement (
154
+ measurement_id, person_id, measurement_concept_id,
155
+ measurement_date, measurement_type_concept_id,
156
+ operator_concept_id, value_as_number,
157
+ unit_concept_id, measurement_source_value
158
+ ) VALUES (
159
+ 110003, 100001, 3013721, -- LOINC: HBsAg
160
+ '2024-06-15', 32817,
161
+ 4171756, -- operator: <
162
+ 0.05, -- value
163
+ 8647, -- IU/mL
164
+ 'HBSAG'
165
+ );
166
+ ```
167
+
168
+ ---
169
+
170
+ ## 4. LOINC — Vocabulary xét nghiệm
171
+
172
+ ### 4.1. LOINC structure
173
+
174
+ ```
175
+ LOINC Code = Component : Property : Time : System : Scale : Method
176
+ VD: 2345-7 = Glucose : MCnc : Pt : Ser/Plas : Qn
177
+
178
+ Component = Glucose (đo gì)
179
+ Property = MCnc (mass concentration)
180
+ Time = Pt (point in time)
181
+ System = Ser/Plas (huyết thanh/huyết tương)
182
+ Scale = Qn (quantitative - số)
183
+ ```
184
+
185
+ ### 4.2. LOINC phổ biến
186
+
187
+ | LOINC Code | Concept ID | Tên | VN |
188
+ |-----------|-----------|-----|-----|
189
+ | 2345-7 | 3004501 | Glucose [Mass/volume] in Serum | Đường huyết |
190
+ | 4548-4 | 3034639 | HbA1c | HbA1c |
191
+ | 2160-0 | 3016723 | Creatinine in Serum | Creatinine máu |
192
+ | 6768-6 | 3006923 | ALT in Serum | SGPT |
193
+ | 33914-3 | 3027018 | GFR estimated | eGFR |
194
+ | 718-7 | 3000963 | Hemoglobin | Hemoglobin |
195
+ | 26515-7 | 3010813 | Platelets | Tiểu cầu |
196
+ | 2093-3 | 3027114 | Total Cholesterol | Cholesterol toàn phần |
197
+
198
+ ---
199
+
200
+ ## 5. unit_concept_id — Đơn vị UCUM
201
+
202
+ | Concept ID | UCUM Code | Đơn vị |
203
+ |-----------|----------|--------|
204
+ | 8840 | mg/dL | Milligrams per deciliter |
205
+ | 8753 | mmol/L | Millimoles per liter |
206
+ | 8647 | IU/mL | International units per milliliter |
207
+ | 8554 | % | Percent |
208
+ | 9529 | kg/m2 | BMI |
209
+ | 8876 | mm[Hg] | Millimeters mercury |
210
+ | 8582 | /uL | Per microliter (blood cells) |
211
+ | 8845 | mg/L | Milligrams per liter |
212
+
213
+ > **Quan trọng:** Cùng một xét nghiệm nhưng đơn vị khác → giá trị khác. VD: Glucose 100 mg/dL = 5.6 mmol/L. ETL phải chuẩn hóa đơn vị!
214
+
215
+ ---
216
+
217
+ ## 6. measurement_event_id — Mới CDM 5.4
218
+
219
+ Cho phép liên kết measurement với bất kỳ event nào khác.
220
+
221
+ ```
222
+ ┌──────────────────────────────┐
223
+ │ MEASUREMENT │
224
+ │ "Lab: BUN = 35 mg/dL" │
225
+ │ measurement_event_id = 70001│
226
+ │ meas_event_field_concept_id │
227
+ │ = 1147127 │──→ condition_occurrence
228
+ │ (condition_occurrence_id)│ .condition_occurrence_id
229
+ └──────────────────────────────┘ = 70001
230
+ ```
231
+
232
+ Ứng dụng: Liên kết xét nghiệm với chẩn đoán hoặc procedure cụ thể đã yêu cầu xét nghiệm đó.
233
+
234
+ ```sql
235
+ -- Xét nghiệm BUN liên quan đến chẩn đoán suy thận
236
+ INSERT INTO measurement (
237
+ measurement_id, person_id, measurement_concept_id,
238
+ measurement_date, measurement_type_concept_id,
239
+ value_as_number, unit_concept_id,
240
+ measurement_event_id,
241
+ meas_event_field_concept_id
242
+ ) VALUES (
243
+ 110010, 100001, 3013682, -- LOINC: BUN
244
+ '2024-06-15', 32817,
245
+ 35, 8840, -- 35 mg/dL
246
+ 70001, -- Liên kết condition_occurrence_id = 70001
247
+ 1147127 -- Field = condition_occurrence.condition_occurrence_id
248
+ );
249
+ ```
250
+
251
+ ---
252
+
253
+ ## 7. ETL xét nghiệm VN
254
+
255
+ ### 7.1. Vấn đề phổ biến
256
+
257
+ | Vấn đề | Giải pháp |
258
+ |--------|-----------|
259
+ | Mã XN nội bộ BV | Map qua SOURCE_TO_CONCEPT_MAP → LOINC |
260
+ | Kết quả text "Dương tính" | Map sang value_as_concept_id |
261
+ | Kết quả "< 0.5" | Tách operator + value_as_number |
262
+ | Đơn vị không chuẩn | Map về UCUM |
263
+ | Range khác nhau theo lab | Lấy range từ máy/lab, nhập range_low/range_high |
264
+ | Bảng XN 20 chỉ số = 1 dòng | Tách thành 20 measurement records |
265
+
266
+ ### 7.2. SQL ETL
267
+
268
+ ```sql
269
+ -- Mỗi chỉ số xét nghiệm = 1 record MEASUREMENT
270
+ SELECT
271
+ ROW_NUMBER() OVER() AS measurement_id,
272
+ pm.person_id,
273
+ COALESCE(stcm.target_concept_id, 0) AS measurement_concept_id,
274
+ xn.ngay_xetnghiem AS measurement_date,
275
+ 32817 AS measurement_type_concept_id,
276
+ -- Parse operator từ giá trị gốc
277
+ CASE
278
+ WHEN xn.gia_tri LIKE '<%' THEN 4171756 -- <
279
+ WHEN xn.gia_tri LIKE '>%' THEN 4172702 -- >
280
+ ELSE 4172703 -- =
281
+ END AS operator_concept_id,
282
+ -- Parse số từ giá trị
283
+ CASE
284
+ WHEN xn.gia_tri ~ '^[<>]?[0-9.]+'
285
+ THEN REGEXP_REPLACE(xn.gia_tri, '[^0-9.]', '', 'g')::FLOAT
286
+ ELSE NULL
287
+ END AS value_as_number,
288
+ -- Kết quả danh mục
289
+ CASE xn.gia_tri
290
+ WHEN 'Dương tính' THEN 4181412 -- Positive
291
+ WHEN 'Âm tính' THEN 4132135 -- Negative
292
+ WHEN 'Bình thường' THEN 4069590 -- Normal
293
+ ELSE NULL
294
+ END AS value_as_concept_id,
295
+ COALESCE(u.target_concept_id, 0) AS unit_concept_id,
296
+ xn.gioi_han_duoi AS range_low,
297
+ xn.gioi_han_tren AS range_high,
298
+ xn.ma_xetnghiem AS measurement_source_value,
299
+ xn.don_vi_goc AS unit_source_value,
300
+ xn.gia_tri AS value_source_value
301
+ FROM xetnghiem_his xn
302
+ JOIN person_mapping pm ON xn.ma_bn = pm.source_id
303
+ LEFT JOIN source_to_concept_map stcm
304
+ ON xn.ma_xetnghiem = stcm.source_code
305
+ AND stcm.source_vocabulary_id = 'VN_LAB'
306
+ LEFT JOIN source_to_concept_map u
307
+ ON xn.don_vi_goc = u.source_code
308
+ AND u.source_vocabulary_id = 'VN_UNIT';
309
+ ```
310
+
311
+ ---
312
+
313
+ ## 8. Sinh hiệu (Vital Signs) trong MEASUREMENT
314
+
315
+ | Sinh hiệu | LOINC | Concept ID | Đơn vị |
316
+ |-----------|-------|-----------|--------|
317
+ | Huyết áp tâm thu | 8480-6 | 3004249 | mmHg |
318
+ | Huyết áp tâm trương | 8462-4 | 3012888 | mmHg |
319
+ | Nhịp tim | 8867-4 | 3027018 | /min |
320
+ | Nhiệt độ | 8310-5 | 3020891 | °C |
321
+ | SpO2 | 59408-5 | 40762499 | % |
322
+ | Cân nặng | 29463-7 | 3025315 | kg |
323
+ | Chiều cao | 8302-2 | 3036277 | cm |
324
+ | BMI | 39156-5 | 3038553 | kg/m² |
325
+
326
+ ```sql
327
+ -- Ghi sinh hiệu: HA 130/85, NT 80, Nhiệt 37.2, SpO2 97%
328
+ INSERT INTO measurement (measurement_id, person_id, measurement_concept_id,
329
+ measurement_date, measurement_type_concept_id,
330
+ value_as_number, unit_concept_id, measurement_source_value)
331
+ VALUES
332
+ (120001, 100001, 3004249, '2024-06-15', 32817, 130, 8876, 'SBP'),
333
+ (120002, 100001, 3012888, '2024-06-15', 32817, 85, 8876, 'DBP'),
334
+ (120003, 100001, 3027018, '2024-06-15', 32817, 80, 8541, 'HR'),
335
+ (120004, 100001, 3020891, '2024-06-15', 32817, 37.2, 586323, 'TEMP'),
336
+ (120005, 100001, 40762499, '2024-06-15', 32817, 97, 8554, 'SPO2');
337
+ ```
338
+
339
+ ---
340
+
341
+ ## 9. SQL phân tích
342
+
343
+ ```sql
344
+ -- Phân bố HbA1c trong dân số
345
+ SELECT
346
+ CASE
347
+ WHEN m.value_as_number < 5.7 THEN 'Bình thường (<5.7%)'
348
+ WHEN m.value_as_number BETWEEN 5.7 AND 6.4 THEN 'Tiền ĐTĐ (5.7-6.4%)'
349
+ WHEN m.value_as_number >= 6.5 THEN 'ĐTĐ (>=6.5%)'
350
+ END AS hba1c_group,
351
+ COUNT(DISTINCT m.person_id) AS patients,
352
+ ROUND(AVG(m.value_as_number), 2) AS avg_hba1c
353
+ FROM measurement m
354
+ WHERE m.measurement_concept_id = 3034639 -- HbA1c
355
+ AND m.value_as_number IS NOT NULL
356
+ AND m.value_as_number BETWEEN 2 AND 20 -- loại outliers
357
+ GROUP BY hba1c_group
358
+ ORDER BY hba1c_group;
359
+
360
+ -- Xu hướng HbA1c theo thời gian (1 BN)
361
+ SELECT
362
+ m.measurement_date,
363
+ m.value_as_number AS hba1c,
364
+ CASE
365
+ WHEN m.value_as_number < 7.0 THEN '✅ Kiểm soát tốt'
366
+ ELSE '⚠️ Cần cải thiện'
367
+ END AS status
368
+ FROM measurement m
369
+ WHERE m.person_id = 100001
370
+ AND m.measurement_concept_id = 3034639
371
+ ORDER BY m.measurement_date;
372
+
373
+ -- Xét nghiệm bất thường (ngoài range)
374
+ SELECT
375
+ c.concept_name AS test_name,
376
+ COUNT(*) AS abnormal_count,
377
+ COUNT(DISTINCT m.person_id) AS patients
378
+ FROM measurement m
379
+ JOIN concept c ON m.measurement_concept_id = c.concept_id
380
+ WHERE m.value_as_number IS NOT NULL
381
+ AND (m.value_as_number < m.range_low
382
+ OR m.value_as_number > m.range_high)
383
+ AND m.range_low IS NOT NULL
384
+ AND m.range_high IS NOT NULL
385
+ GROUP BY c.concept_name
386
+ ORDER BY abnormal_count DESC
387
+ LIMIT 10;
388
+ ```
389
+
390
+ ---
391
+
392
+ ## Tổng kết
393
+
394
+ 1. **MEASUREMENT** = xét nghiệm + sinh hiệu + mọi giá trị đo được
395
+ 2. Hai loại kết quả: **value_as_number** (số) hoặc **value_as_concept_id** (danh mục)
396
+ 3. **operator_concept_id** cho kết quả "<" hoặc ">"
397
+ 4. **unit_concept_id** dùng UCUM, **measurement_concept_id** dùng LOINC
398
+ 5. **range_low / range_high** cho giá trị tham chiếu bình thường
399
+ 6. CDM 5.4: **measurement_event_id** liên kết xét nghiệm với event khác
400
+
401
+ **Bài tiếp theo:** OBSERVATION — sự kiện lâm sàng không thuộc các bảng chuyên biệt.
402
+
403
+ ---
404
+
405
+ ## Tài liệu tham khảo
406
+
407
+ - [OMOP CDM 5.4 — MEASUREMENT](https://ohdsi.github.io/CommonDataModel/cdm54.html#MEASUREMENT)
408
+ - [LOINC.org](https://loinc.org/)
409
+ - [UCUM — Unified Code for Units of Measure](https://ucum.org/)
@@ -0,0 +1,285 @@
1
+ ---
2
+ id: 019f1a00-a107-7b01-e001-omopcdm54007
3
+ title: "Bài 7: CONDITION_OCCURRENCE — Chẩn đoán & Bệnh lý"
4
+ slug: bai-7-condition-occurrence-chan-doan-benh-ly
5
+ description: >-
6
+ Ghi nhận chẩn đoán, triệu chứng, dấu hiệu bệnh lý,
7
+ condition_concept_id vs source_value, condition_status
8
+ (admitting/primary/secondary), liên kết với Visit và Provider,
9
+ phân biệt với OBSERVATION table.
10
+ duration_minutes: 60
11
+ is_free: true
12
+ video_url: null
13
+ sort_order: 7
14
+ section_title: "Phần 3: Sự kiện lâm sàng chính"
15
+ course:
16
+ id: 019f1a00-a100-7b01-e001-omopcdm54001
17
+ title: "OMOP CDM 5.4 cho Người mới — Hiểu từ A đến Z"
18
+ slug: omop-cdm-5-4-cho-nguoi-moi-bat-dau
19
+ ---
20
+
21
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 340" style="max-width: 100%; height: auto; border-radius: 12px; margin-bottom: 1.5rem;">
22
+ <defs>
23
+ <linearGradient id="bg-omop07" x1="0%" y1="0%" x2="100%" y2="100%">
24
+ <stop offset="0%" style="stop-color:#0c1222"/>
25
+ <stop offset="100%" style="stop-color:#1e293b"/>
26
+ </linearGradient>
27
+ </defs>
28
+ <rect width="1200" height="340" rx="12" fill="url(#bg-omop07)"/>
29
+ <g>
30
+ <circle cx="659" cy="87" r="22" fill="#818cf8" opacity="0.12"/>
31
+ <circle cx="718" cy="106" r="29" fill="#818cf8" opacity="0.09"/>
32
+ <circle cx="777" cy="125" r="36" fill="#818cf8" opacity="0.06"/>
33
+ <circle cx="895" cy="163" r="20" fill="#818cf8" opacity="0.1"/>
34
+ <line x1="600" y1="157" x2="1100" y2="237" stroke="#818cf8" stroke-width="0.5" opacity="0.1"/>
35
+ </g>
36
+ <rect x="60" y="50" width="4" height="60" rx="2" fill="#818cf8"/>
37
+ <rect x="80" y="50" width="121" height="28" rx="14" fill="#818cf8" opacity="0.15"/>
38
+ <text x="92" y="69" font-family="system-ui,-apple-system,sans-serif" font-size="13" font-weight="600" fill="#818cf8">🏗️ Kiến trúc — Bài 7</text>
39
+ <text x="60" y="140" font-family="system-ui,-apple-system,sans-serif" font-size="34" font-weight="700" fill="#f1f5f9">
40
+ <tspan x="60" dy="0">CONDITION_OCCURRENCE</tspan>
41
+ <tspan x="60" dy="42">Chẩn đoán &amp; Bệnh lý</tspan>
42
+ </text>
43
+ <text x="60" y="244" font-family="system-ui,-apple-system,sans-serif" font-size="15" fill="#94a3b8" opacity="0.8">OMOP CDM 5.4 cho Người mới — Hiểu từ A đến Z</text>
44
+ <text x="60" y="268" font-family="system-ui,-apple-system,sans-serif" font-size="13" fill="#64748b" opacity="0.6">Phần 3: Sự kiện lâm sàng chính</text>
45
+ <text x="1140" y="320" font-family="system-ui,-apple-system,sans-serif" font-size="12" fill="#475569" text-anchor="end" opacity="0.4">xdev.asia</text>
46
+ </svg>
47
+
48
+ ![Quy trình mapping ICD-10 → SNOMED trong CONDITION_OCCURRENCE](/storage/uploads/2026/04/omop-cdm-bai7-condition-mapping.png)
49
+
50
+ ## Giới thiệu
51
+
52
+ **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ì?"
53
+
54
+ ---
55
+
56
+ ## 1. Cấu trúc bảng
57
+
58
+ | Cột | Kiểu | Bắt buộc | Mô tả |
59
+ |-----|------|----------|-------|
60
+ | `condition_occurrence_id` | INTEGER | ✅ PK | ID duy nhất |
61
+ | `person_id` | INTEGER | ✅ FK | Bệnh nhân |
62
+ | `condition_concept_id` | INTEGER | ✅ | Standard Concept (SNOMED) |
63
+ | `condition_start_date` | DATE | ✅ | Ngày bắt đầu chẩn đoán |
64
+ | `condition_start_datetime` | DATETIME | | Ngày giờ |
65
+ | `condition_end_date` | DATE | | Ngày hết chẩn đoán |
66
+ | `condition_end_datetime` | DATETIME | | Ngày giờ kết thúc |
67
+ | `condition_type_concept_id` | INTEGER | ✅ | Nguồn dữ liệu |
68
+ | `condition_status_concept_id` | INTEGER | | Trạng thái (Primary, Admitting...) |
69
+ | `stop_reason` | VARCHAR(20) | | Lý do ngưng chẩn đoán |
70
+ | `provider_id` | INTEGER | FK | Bác sĩ chẩn đoán |
71
+ | `visit_occurrence_id` | INTEGER | FK | Visit liên quan |
72
+ | `visit_detail_id` | INTEGER | FK | Visit detail (khoa nào) |
73
+ | `condition_source_value` | VARCHAR(50) | | Mã gốc (VD: "E11") |
74
+ | `condition_source_concept_id` | INTEGER | | Concept gốc |
75
+ | `condition_status_source_value` | VARCHAR(50) | | Status gốc |
76
+
77
+ ---
78
+
79
+ ## 2. Lưu gì vào CONDITION_OCCURRENCE?
80
+
81
+ ### 2.1. NÊN lưu
82
+
83
+ | Loại | Ví dụ | Vocabulary |
84
+ |------|-------|------------|
85
+ | Chẩn đoán bệnh | Tiểu đường type 2, Viêm phổi | SNOMED CT |
86
+ | Triệu chứng | Sốt, Đau bụng, Ho | SNOMED CT |
87
+ | Dấu hiệu lâm sàng | Phù chân, Vàng da | SNOMED CT |
88
+ | Chẩn đoán phân biệt | Nghi ngờ lao phổi | SNOMED CT |
89
+
90
+ ### 2.2. KHÔNG NÊN lưu (lưu ở bảng khác)
91
+
92
+ | Loại | Bảng đích | Lý do |
93
+ |------|-----------|-------|
94
+ | "Tiền sử tiểu đường" | OBSERVATION | Domain = Observation |
95
+ | "Không bị dị ứng" | OBSERVATION | Absence → Observation |
96
+ | "BMI = 28" | MEASUREMENT | Domain = Measurement |
97
+ | Tác dụng phụ thuốc | CONDITION + DRUG_EXPOSURE | Condition cho ADR, Drug cho thuốc gây ra |
98
+
99
+ ---
100
+
101
+ ## 3. condition_status_concept_id — Trạng thái chẩn đoán
102
+
103
+ | Concept ID | Status | Ý nghĩa |
104
+ |-----------|--------|---------|
105
+ | 32902 | Primary diagnosis | Chẩn đoán chính |
106
+ | 32908 | Secondary diagnosis | Chẩn đoán phụ |
107
+ | 32903 | Admitting diagnosis | Chẩn đoán lúc nhập viện |
108
+ | 32904 | Discharge diagnosis | Chẩn đoán lúc xuất viện |
109
+ | 32906 | Provisional diagnosis | Chẩn đoán tạm thời |
110
+ | 32907 | Confirmed diagnosis | Chẩn đoán xác nhận |
111
+
112
+ ```sql
113
+ -- Ví dụ: BN nhập viện
114
+ -- Chẩn đoán nhập viện: Nghi lao phổi (provisional)
115
+ INSERT INTO condition_occurrence VALUES (
116
+ 70001, 100001, 255848, -- SNOMED: Pneumonia
117
+ '2024-06-10', NULL,
118
+ '2024-06-20', NULL,
119
+ 32817, -- EHR
120
+ 32903, -- Admitting diagnosis
121
+ NULL, 5001, 50001, NULL,
122
+ 'J18.9', 0, -- ICD-10: Pneumonia, unspecified
123
+ 'admitting'
124
+ );
125
+
126
+ -- Chẩn đoán xuất viện: Viêm phổi do phế cầu (confirmed)
127
+ INSERT INTO condition_occurrence VALUES (
128
+ 70002, 100001, 257315, -- SNOMED: Pneumococcal pneumonia
129
+ '2024-06-10', NULL,
130
+ '2024-06-20', NULL,
131
+ 32817, -- EHR
132
+ 32904, -- Discharge diagnosis
133
+ NULL, 5001, 50001, NULL,
134
+ 'J13', 0, -- ICD-10
135
+ 'discharge'
136
+ );
137
+ ```
138
+
139
+ ---
140
+
141
+ ## 4. ETL cho dữ liệu ICD-10 Việt Nam
142
+
143
+ ### 4.1. Quy trình mapping
144
+
145
+ ```
146
+ HIS: ma_benh = 'E11.65' (ICD-10-CM)
147
+ ten_benh = 'ĐTĐ type 2 có biến chứng mạch máu ngoại vi'
148
+
149
+ │ Bước 1: Tìm source concept
150
+
151
+ SOURCE CONCEPT: concept_id = 45591837
152
+ vocabulary_id = ICD10CM
153
+ concept_code = 'E11.65'
154
+
155
+ │ Bước 2: Tìm Standard Concept (Maps to)
156
+
157
+ STANDARD CONCEPT: concept_id = 201826
158
+ vocabulary_id = SNOMED
159
+ concept_name = 'Type 2 diabetes mellitus'
160
+ domain_id = 'Condition'
161
+ ```
162
+
163
+ ```sql
164
+ -- SQL ETL
165
+ SELECT
166
+ ROW_NUMBER() OVER() AS condition_occurrence_id,
167
+ pm.person_id,
168
+ COALESCE(cr.concept_id_2, 0) AS condition_concept_id,
169
+ cd.ngay_chandoan AS condition_start_date,
170
+ NULL AS condition_end_date,
171
+ 32817 AS condition_type_concept_id,
172
+ CASE cd.loai_chandoan
173
+ WHEN 'CHINH' THEN 32902 -- Primary
174
+ WHEN 'PHU' THEN 32908 -- Secondary
175
+ ELSE 0
176
+ END AS condition_status_concept_id,
177
+ cd.ma_icd10 AS condition_source_value,
178
+ COALESCE(c_source.concept_id, 0) AS condition_source_concept_id
179
+ FROM chandoan_his cd
180
+ JOIN person_mapping pm ON cd.ma_bn = pm.source_id
181
+ LEFT JOIN concept c_source
182
+ ON cd.ma_icd10 = c_source.concept_code
183
+ AND c_source.vocabulary_id = 'ICD10CM'
184
+ LEFT JOIN concept_relationship cr
185
+ ON c_source.concept_id = cr.concept_id_1
186
+ AND cr.relationship_id = 'Maps to'
187
+ LEFT JOIN concept c_std
188
+ ON cr.concept_id_2 = c_std.concept_id
189
+ AND c_std.standard_concept = 'S';
190
+ ```
191
+
192
+ ### 4.2. Xử lý dữ liệu đặc thù VN
193
+
194
+ | Vấn đề | Giải pháp |
195
+ |--------|-----------|
196
+ | ICD-10-VN khác ICD-10-CM | Mapping qua SOURCE_TO_CONCEPT_MAP |
197
+ | Mã nội bộ BV | Usagi mapping tool |
198
+ | Thiếu ngày kết thúc | condition_end_date = NULL (hợp lệ) |
199
+ | 1 ICD map nhiều SNOMED | Chọn concept phù hợp nhất |
200
+
201
+ ---
202
+
203
+ ## 5. Phân biệt CONDITION vs OBSERVATION
204
+
205
+ | Tiêu chí | CONDITION_OCCURRENCE | OBSERVATION |
206
+ |-----------|---------------------|-------------|
207
+ | **Nội dung** | Bệnh hiện tại / đang điều trị | Tiền sử, lối sống, ghi nhận |
208
+ | **Ví dụ** | "Tiểu đường type 2" | "Tiền sử tiểu đường gia đình" |
209
+ | **Domain** | Condition | Observation |
210
+ | **Standard Vocab** | SNOMED CT | SNOMED CT |
211
+ | **Khi nào?** | Bệnh đang hoạt động | Ghi nhận thông tin |
212
+
213
+ > **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.
214
+
215
+ ---
216
+
217
+ ## 6. SQL phân tích phổ biến
218
+
219
+ ```sql
220
+ -- Top 10 chẩn đoán phổ biến nhất
221
+ SELECT
222
+ c.concept_name AS condition_name,
223
+ COUNT(DISTINCT co.person_id) AS patient_count,
224
+ COUNT(*) AS record_count
225
+ FROM condition_occurrence co
226
+ JOIN concept c ON co.condition_concept_id = c.concept_id
227
+ WHERE co.condition_concept_id != 0
228
+ GROUP BY c.concept_name
229
+ ORDER BY patient_count DESC
230
+ LIMIT 10;
231
+
232
+ -- Tỉ lệ mắc bệnh theo giới tính
233
+ SELECT
234
+ g.concept_name AS gender,
235
+ c.concept_name AS condition_name,
236
+ COUNT(DISTINCT co.person_id) AS patients
237
+ FROM condition_occurrence co
238
+ JOIN person p ON co.person_id = p.person_id
239
+ JOIN concept g ON p.gender_concept_id = g.concept_id
240
+ JOIN concept c ON co.condition_concept_id = c.concept_id
241
+ WHERE co.condition_concept_id = 201826 -- Type 2 DM
242
+ GROUP BY g.concept_name, c.concept_name;
243
+
244
+ -- Comorbidity: BN tiểu đường có tăng huyết áp?
245
+ SELECT
246
+ COUNT(DISTINCT co_dm.person_id) AS dm_patients,
247
+ COUNT(DISTINCT co_ht.person_id) AS dm_with_hypertension,
248
+ ROUND(
249
+ COUNT(DISTINCT co_ht.person_id) * 100.0 /
250
+ NULLIF(COUNT(DISTINCT co_dm.person_id), 0), 1
251
+ ) AS comorbidity_pct
252
+ FROM condition_occurrence co_dm
253
+ LEFT JOIN condition_occurrence co_ht
254
+ ON co_dm.person_id = co_ht.person_id
255
+ AND co_ht.condition_concept_id IN (
256
+ SELECT descendant_concept_id
257
+ FROM concept_ancestor
258
+ WHERE ancestor_concept_id = 320128 -- Essential hypertension
259
+ )
260
+ WHERE co_dm.condition_concept_id IN (
261
+ SELECT descendant_concept_id
262
+ FROM concept_ancestor
263
+ WHERE ancestor_concept_id = 201826 -- Type 2 DM
264
+ );
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Tổng kết
270
+
271
+ 1. **CONDITION_OCCURRENCE** = chẩn đoán, triệu chứng, dấu hiệu bệnh lý
272
+ 2. **condition_concept_id** dùng Standard Concept (SNOMED CT)
273
+ 3. **condition_status**: Primary, Secondary, Admitting, Discharge
274
+ 4. **Bộ ba cột**: concept_id / source_value / source_concept_id
275
+ 5. **Phân biệt** CONDITION (bệnh hiện tại) vs OBSERVATION (tiền sử, ghi nhận)
276
+ 6. **ETL VN**: ICD-10-VN → Source Concept → Maps to → Standard SNOMED
277
+
278
+ **Bài tiếp theo:** DRUG_EXPOSURE — cách OMOP CDM ghi nhận thuốc, kê đơn, và vaccine.
279
+
280
+ ---
281
+
282
+ ## Tài liệu tham khảo
283
+
284
+ - [OMOP CDM 5.4 — CONDITION_OCCURRENCE](https://ohdsi.github.io/CommonDataModel/cdm54.html#CONDITION_OCCURRENCE)
285
+ - [Athena — Condition Domain](https://athena.ohdsi.org/)