En résumé
OMOP CDM est un modèle de base de données relationnelle conçu pour rendre les données de santé interrogeables de la même façon dans tous les hôpitaux et toutes les bases qui l’adoptent. On y trouve une quarantaine de tables organisées en six grandes catégories — cliniques, système de santé, vocabulaires, économie de santé, éléments dérivés, métadonnées — toutes articulées autour d’un principe simple : tout événement clinique est rattaché à une personne et à une date. La version 5.4, stable depuis 2021, est aujourd’hui la version de référence dans la communauté OHDSI.
Ce que vous savez déjà
Les articles précédents de cette section ont posé le pourquoi d’OMOP (le projet initial, sa communauté, l’idée d’un format commun). Cet article ouvre le comment : à quoi ressemble concrètement le modèle lorsqu’on examine sa structure.
Pour suivre, il suffit de garder en tête quelques notions vues dans la section Comprendre les entrepôts de données de santé :
- Une base de données relationnelle est une collection de tables reliées entre elles par des clés — des colonnes partagées dont la valeur identifie un même objet d’une table à l’autre (par exemple
person_id, qui apparaît dans toutes les tables d’événements pour rattacher chaque ligne à un patient unique de la tablePERSON). C’est exactement la logique décrite dans l’article Comment sont organisées les données de santé ?. - Les données de santé sont structurées au format long : une ligne par événement, des colonnes pour qualifier cet événement.
- Les codes médicaux (CIM-10, SNOMED CT, LOINC…) sont conservés sous une forme standardisée pour permettre la comparabilité entre bases.
OMOP CDM applique ces principes de manière rigoureuse : un schéma relationnel précisément spécifié, identique d’une institution à l’autre. C’est ce schéma que nous détaillons à partir d’ici.
Une brève histoire des versions
Le Common Data Model n’est pas figé : il évolue par versions, publiées par OHDSI sur GitHub. Connaître l’historique aide à comprendre la version qu’on utilise — et celles qu’on évite.
CDM v5.3 — janvier 2019
Version stable pendant deux ans et demi, qui a servi de socle à beaucoup d’entrepôts OMOP mis en place pendant cette période. Encore présente dans des bases qui n’ont pas migré vers la 5.4.
CDM v5.4 — septembre 2021
Version actuelleApporte les tables EPISODE et EPISODE_EVENT, intègre COHORT dans le modèle, et ajoute plusieurs champs aux tables existantes (coordonnées géographiques dans LOCATION, etc.). La liste complète des changements est documentée ici. C’est la version de référence aujourd’hui — stable depuis plus de quatre ans, ce qui est une force du modèle.
CDM v6.0 — octobre 2021, mise en pause
Cette version rendait obligatoires les champs datetime (heure précise) là où ils étaient auparavant optionnels. Le README officiel indique que v6.0 « n’est pas pleinement supporté par les outils et méthodes OHDSI » et recommande explicitement aux institutions de rester sur v5.4 le temps que la communauté tranche le rôle des dates par rapport aux datetime.
CDM v5.5 — prévue pour août 2026
Une évolution incrémentale est en préparation, suivie publiquement dans le milestone GitHub officiel, échéance août 2026. Au menu, entre autres : une nouvelle table PACK_CONTENT qui décrit la composition des packs de médicaments (quels principes actifs, en quelle quantité, dans quel conditionnement), un champ VALUE_AS_DATE dans OBSERVATION, et plusieurs corrections de clés étrangères. Nous mettrons cet article à jour quand la version sera publiée.
Les grandes catégories de tables
Le CDM v5.4 organise sa quarantaine de tables en six grandes catégories. Toutes ne sont pas utilisées dans toutes les bases : la plupart des entrepôts hospitaliers se concentrent sur les données cliniques et le système de santé.
Données cliniques standardisées
Les patients eux-mêmes, leurs hospitalisations, diagnostics, médicaments, examens biologiques et gestes médicaux. C’est le cœur du modèle, ce qui est observé sur les patients.
Vocabulaires standardisés
Le dictionnaire des concepts médicaux : codes, libellés, relations entre concepts et hiérarchies. Sujet de l’article suivant.
Système de santé standardisé
Le contexte de soin : les services hospitaliers, les professionnels de santé, et les lieux géographiques où les soins ont eu lieu.
Éléments dérivés standardisés
Des agrégations pré-calculées à partir des données cliniques, conçues pour accélérer les analyses récurrentes (par exemple regrouper plusieurs prescriptions successives en une période d’exposition continue).
Économie de la santé standardisée
Les coûts et remboursements associés aux soins, principalement renseignés dans les bases d’assurance maladie.
Métadonnées standardisées
La description de l’entrepôt lui-même : version du CDM utilisée, périmètre couvert, informations techniques sur l’instance.
L'explorateur interactif
Pour voir le détail de chaque table (colonnes, types de données, clés primaires et étrangères, contraintes), utilisez notre explorateur interactif du schéma OMOP v5.4. Il couvre l’ensemble des tables du modèle, avec des renvois entre elles.
Trois conventions fondamentales
Avant de plonger dans les tables une à une, trois principes structurent tout le modèle. Les comprendre vous fera gagner beaucoup de temps en pratique.
1. Modèle centré patient
Chaque enregistrement, dans toutes les tables d’événements, est associé à un identifiant patient (person_id) et à au moins une date. C’est la garantie que toute analyse peut produire une vue longitudinale de la santé d’un patient.
Les domaines sont modélisés dans un schéma relationnel centré patient, où chaque enregistrement comporte au minimum l’identité de la personne et une date.
2. Dualité source / standard
C’est probablement la convention OMOP la plus importante à comprendre. Pour chaque événement clinique, le modèle conserve deux représentations en parallèle :
- Le code source original tel qu’il existe dans le système hospitalier (par exemple un code CIM-10 pour un diagnostic).
- Le concept standardisé OMOP vers lequel ce code source a été mappé (par exemple le concept SNOMED CT équivalent).
Concrètement, chaque table d’événements suit le même patron de colonnes :
- <event>_concept_id : identifiant du concept standard OMOP
- <event>_source_value : code/libellé source tel quel
- <event>_source_concept_id : concept OMOP correspondant au code source
Exemple concret — une fréquence cardiaque dans MEASUREMENT
Imaginons que le moniteur d’un service de réanimation enregistre la fréquence cardiaque sous le libellé local « FC bpm », sans code structuré. Voici à quoi ressemble la ligne après l’ETL OMOP :
| Colonne | Valeur | Lecture |
|---|---|---|
| measurement_concept_id | 3027018 | Le concept standard OMOP pour Heart rate (mappé sur LOINC 8867-4). |
| measurement_source_value | FC bpm | Le libellé tel qu’il existait dans le système source, conservé pour la traçabilité. |
| measurement_source_concept_id | 0 | « FC bpm » n’est pas un code structuré reconnu : aucun concept source à attacher, donc 0. |
Si la source avait utilisé directement le code LOINC 8867-4, alors measurement_source_concept_id aurait également valu 3027018 : LOINC étant un vocabulaire standard d’OMOP, le code source et le concept standard coïncident.
Pourquoi cette double représentation ? Parce qu’elle permet à la fois la comparabilité internationale (via le concept standard) et la traçabilité (en conservant le code source original, on peut toujours vérifier la donnée à la source).
Concept_id = 0, le 'NULL' d'OMOP
Quand un code source n’a pas de mapping vers un concept standard, son <event>_concept_id vaut 0. C’est le « flavor of NULL » d’OMOP — il signale un concept non standardisé sans qu’on ait à filtrer les valeurs nulles SQL classiques. Les requêtes de qualité commencent souvent par compter les concept_id = 0.
3. Le type_concept_id : d’où vient cet enregistrement ?
Beaucoup de tables incluent une colonne <event>_type_concept_id. Attention au piège : ce n’est pas une catégorisation de l’événement lui-même, mais une indication de sa provenance.
Par exemple, pour un médicament dans DRUG_EXPOSURE, le drug_type_concept_id indique si la donnée vient d’une prescription, d’une dispensation ou d’une administration — pas la nature du médicament.
C’est utile pour la qualité : on peut vouloir restreindre une analyse aux médicaments effectivement dispensés ou administrés, pas seulement prescrits.
Ces trois conventions en tête, abordons maintenant les principales tables du modèle. Nous les regroupons en deux familles : d’abord celles qui décrivent le patient et son parcours dans le système de soins, puis celles qui décrivent les événements cliniques observés au fil de ce parcours.
Le patient et son parcours
PERSON — la table des patients
- Rôle :
- Démographie du patient (sexe, année de naissance, origine).
- Une ligne par :
- Patient unique dans la base.
- Connectée à :
- Toutes les tables cliniques via
person_id. C’est le point d’ancrage du modèle.
Tout commence par PERSON. C’est la table de démographie : une ligne par patient unique dans la base.
| Colonne | Contenu |
|---|---|
person_id | Identifiant unique du patient (clé primaire) |
gender_concept_id | Sexe sous forme de concept standard OMOP |
year_of_birth | Année de naissance (seul champ obligatoire pour la date de naissance) |
month_of_birth, day_of_birth | Optionnels, selon ce qui est disponible à la source |
race_concept_id, ethnicity_concept_id | Catégories démographiques standardisées |
location_id, provider_id, care_site_id | Liens vers les tables de contexte |
Notez la nuance entre year_of_birth (obligatoire) et month_of_birth/day_of_birth (optionnels). Le modèle accepte qu’une date de naissance soit partiellement connue — c’est fréquent dans les bases de remboursement.
Aperçu de la table
Trois patients distincts, chacun avec son identifiant person_id. Deux femmes et un homme, nés entre 1958 et 1985. Pour la patiente 1042, on connaît la date de naissance complète (12 avril 1958).
| person_id | gender_concept_id | year_of_birth | month_of_birth | day_of_birth |
|---|---|---|---|---|
| 1042 | 8532 (Female) | 1958 | 4 | 12 |
| 1043 | 8507 (Male) | 1972 | NULL | NULL |
| 1044 | 8532 (Female) | 1985 | NULL | NULL |
VISIT_OCCURRENCE — les contacts avec le système de santé
- Rôle :
- Décrit chaque contact du patient avec le système de soins (hospitalisation, consultation, urgence…).
- Une ligne par :
- Visite (un même patient en a généralement plusieurs au fil du temps).
- Connectée à :
PERSON,CARE_SITE, et toutes les tables d’événements cliniques qui la référencent viavisit_occurrence_id.
Chaque contact du patient avec le système de soins (hospitalisation, consultation externe, urgence…) génère une ligne dans VISIT_OCCURRENCE.
| Colonne | Contenu |
|---|---|
visit_occurrence_id | Identifiant unique de la visite |
person_id | Le patient concerné |
visit_concept_id | Type de visite (hospitalisation, urgence, consultation…) |
visit_start_date, visit_end_date | Bornes temporelles |
care_site_id | Service ou établissement |
visit_source_value | Libellé source de la visite |
Aperçu de la table
Trois visites pour deux patients. La patiente 1042 a été hospitalisée une semaine en mars puis revue en consultation externe deux mois plus tard. Le patient 1043, lui, est passé aux urgences sans hospitalisation (visite d’une journée).
| visit_occurrence_id | person_id | visit_concept_id | visit_start_date | visit_end_date | care_site_id |
|---|---|---|---|---|---|
| 78201 | 1042 | 9201 (Inpatient Visit) | 2022-03-14 | 2022-03-21 | 12 |
| 78202 | 1042 | 9202 (Outpatient Visit) | 2022-05-02 | 2022-05-02 | 47 |
| 78203 | 1043 | 9203 (Emergency Room Visit) | 2023-11-08 | 2023-11-08 | 8 |
VISIT_DETAIL — les séjours par unité dans une hospitalisation
- Rôle :
- Découpe une hospitalisation en séjours par unité : urgences, réanimation, médecine, chirurgie…
- Une ligne par :
- Séjour dans une unité (une hospitalisation longue en génère plusieurs).
- Connectée à :
VISIT_OCCURRENCE(le séjour parent),PERSON, etCARE_SITE.
Lors d’une hospitalisation, un patient peut transiter par plusieurs services : urgences à l’arrivée, réanimation, puis service de médecine pour la suite. VISIT_DETAIL capture ces étapes intermédiaires, chaque ligne pointant vers la visit_occurrence_id du séjour parent — on garde ainsi une vue d’ensemble tout en pouvant analyser chaque passage en unité.
| Colonne | Contenu |
|---|---|
visit_detail_id | Identifiant unique du sous-séjour |
visit_occurrence_id | Lien vers la visite parente |
person_id | Le patient |
visit_detail_concept_id | Type de sous-séjour (réanimation, hospitalisation classique…) |
visit_detail_start_date, visit_detail_end_date | Bornes temporelles |
care_site_id | Service précis (médecine, chirurgie, cardiologie…) |
parent_visit_detail_id | Pour modéliser des sous-séjours hiérarchisés |
Aperçu de la table — décomposition du séjour 78201
Le séjour 78201 de la patiente 1042 (hospitalisation d’une semaine) est ici décomposé en trois sous-séjours : un passage aux urgences le jour de l’admission, trois jours en réanimation, puis quatre jours en médecine. Toutes ces lignes pointent vers la même visit_occurrence_id.
À noter : OMOP standardise peu les unités hospitalières — seule la réanimation a un concept dédié (32037 Intensive Care). Pour les autres séjours hospitaliers, on retombe sur le concept générique 9201 Inpatient Visit, et le service précis est porté par care_site_id.
| visit_detail_id | visit_occurrence_id | person_id | visit_detail_concept_id | visit_detail_start_date | visit_detail_end_date | care_site_id |
|---|---|---|---|---|---|---|
| 91001 | 78201 | 1042 | 9203 (Emergency Room Visit) | 2022-03-14 | 2022-03-14 | 8 |
| 91002 | 78201 | 1042 | 32037 (ICU) | 2022-03-14 | 2022-03-17 | 23 |
| 91003 | 78201 | 1042 | 9201 (Inpatient Visit) | 2022-03-17 | 2022-03-21 | 12 |
Les événements cliniques
Liens systématiques vers le parcours patient
Toutes les tables d’événements cliniques qui suivent (MEASUREMENT, OBSERVATION, CONDITION_OCCURRENCE, PROCEDURE_OCCURRENCE, DRUG_EXPOSURE) contiennent les mêmes clés étrangères vers le parcours du patient : person_id (vers PERSON), visit_occurrence_id (vers VISIT_OCCURRENCE) et visit_detail_id (vers VISIT_DETAIL). C’est ce qui permet, en quelques jointures, de remonter de n’importe quel événement à son patient, son séjour, et l’unité où il a eu lieu.
MEASUREMENT — les valeurs quantifiables
- Rôle :
- Stocke les valeurs cliniques quantifiables : résultats de biologie, signes vitaux, scores cliniques.
- Une ligne par :
- Mesure enregistrée (un même paramètre est mesuré plusieurs fois pendant un séjour).
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et au vocabulaire LOINC côté standard.
MEASUREMENT contient tout ce qui se mesure avec une valeur — chiffre, intervalle, résultat catégoriel codé.
| Colonne | Contenu |
|---|---|
measurement_id | Identifiant unique de la mesure |
person_id | Le patient |
measurement_concept_id | Concept standard (LOINC le plus souvent) |
measurement_date, measurement_datetime | Date (et heure si disponible) de la mesure |
value_as_number | Valeur numérique |
value_as_concept_id | Valeur codée (pour les résultats qualitatifs : positif/négatif, etc.) |
unit_concept_id | Unité de la valeur |
range_low, range_high | Bornes de référence pour la mesure |
visit_occurrence_id, visit_detail_id | Contexte de la mesure |
measurement_source_value | Libellé source |
Aperçu de la table
Trois mesures prises pour la patiente 1042 pendant son hospitalisation : une fréquence cardiaque (88/min), une température en fièvre légère (38,6 °C), et une urée sanguine. Chaque ligne associe un concept LOINC à sa valeur numérique et son unité.
| measurement_id | person_id | measurement_concept_id | measurement_date | value_as_number | unit_concept_id |
|---|---|---|---|---|---|
| 220841 | 1042 | 3027018 (Heart rate) | 2022-03-14 | 88 | 8541 (/min) |
| 220842 | 1042 | 3020891 (Body temperature) | 2022-03-14 | 38.6 | 586323 (°C) |
| 220843 | 1042 | 3013682 (Urea nitrogen) | 2022-03-15 | 7.2 | 8753 (mmol/L) |
OBSERVATION — les faits cliniques sans valeur numérique
- Rôle :
- Stocke les faits cliniques sans valeur numérique naturelle : signes cliniques, mode de vie, motif de consultation.
- Une ligne par :
- Fait clinique observé pour un patient.
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et SNOMED CT le plus souvent.
OBSERVATION accueille les événements cliniques qui ne trouvent leur place dans aucune autre table de domaine : statut tabagique, profession, motif de consultation, antécédents familiaux, score qualitatif, exposition environnementale… Quand un concept n’appartient pas aux domaines Condition, Drug, Procedure ou Measurement, c’est ici qu’il atterrit.
| Colonne | Contenu |
|---|---|
observation_id | Identifiant unique de l’observation |
person_id | Le patient |
observation_concept_id | Concept standard (SNOMED CT le plus souvent) |
observation_date, observation_datetime | Date (et heure si disponible) de l’observation |
value_as_number | Valeur numérique si pertinente |
value_as_string | Valeur textuelle (réponse libre) |
value_as_concept_id | Valeur codée |
qualifier_concept_id | Précision sur l’observation |
visit_occurrence_id, visit_detail_id | Contexte |
observation_source_value | Libellé source |
Une question fréquente : où va telle ou telle donnée — MEASUREMENT ou OBSERVATION ? La règle officielle est que le domaine du concept détermine la table : un concept de domaine Measurement va dans MEASUREMENT, un concept de domaine Observation dans OBSERVATION. ATHENA donne le domaine de chaque concept.
Aperçu de la table
Trois faits cliniques sans valeur numérique : un statut tabagique pour la patiente 1042 (Yes), un autre, plus nuancé, pour le patient 1043 (ancien fumeur), et le motif de consultation de la patiente 1044 (check-up). La colonne value_as_string stocke ici la réponse en texte.
| observation_id | person_id | observation_concept_id | observation_date | value_as_string |
|---|---|---|---|---|
| 404001 | 1042 | 40766306 (Smoked ≥ 100 cig.) | 2022-03-14 | Yes |
| 404002 | 1043 | 43054909 (Tobacco smoking status) | 2023-11-08 | Former smoker |
| 404003 | 1044 | 3025141 (Reason for visit) | 2024-02-19 | Routine check-up |
CONDITION_OCCURRENCE — les diagnostics
- Rôle :
- Recense les diagnostics posés pour un patient (principal, comorbidités, liste de problèmes…).
- Une ligne par :
- Diagnostic enregistré (une visite peut générer plusieurs lignes).
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et aux vocabulaires (SNOMED CT côté standard, CIM-10 côté source).
Chaque diagnostic posé pour un patient devient une ligne dans CONDITION_OCCURRENCE. Une admission peut générer plusieurs lignes (un diagnostic principal + plusieurs comorbidités).
| Colonne | Contenu |
|---|---|
condition_occurrence_id | Identifiant unique du diagnostic |
person_id | Le patient |
condition_concept_id | Concept standard (SNOMED CT le plus souvent) |
condition_start_date | Date de début |
condition_end_date | Date de fin si connue (chronique ou résolu) |
visit_occurrence_id | Lien vers la visite associée |
condition_source_value | Code source (souvent CIM-10) |
condition_source_concept_id | Concept correspondant au code source |
condition_type_concept_id | Provenance : diagnostic principal, comorbidité, liste de problèmes… |
Aperçu de la table
Trois diagnostics. La patiente 1042 a un diabète de type 2 connu depuis 2019 et une HTA diagnostiquée pendant son hospitalisation de 2022. Le patient 1043 a fait un infarctus en novembre 2023. Chaque ligne illustre la dualité source/standard : le concept SNOMED CT standard (condition_concept_id), le code CIM-10 source brut (condition_source_value) et son concept OMOP correspondant (condition_source_concept_id) sont conservés en parallèle.
| condition_occurrence_id | person_id | condition_concept_id | condition_start_date | visit_occurrence_id | condition_source_value | condition_source_concept_id |
|---|---|---|---|---|---|---|
| 601201 | 1042 | 201826 (T2 diabetes) | 2019-06-22 | 78101 | E11.9 | 45561952 (ICD10 E11.9) |
| 601202 | 1042 | 320128 (Essential HTN) | 2022-03-14 | 78201 | I10 | 45591453 (ICD10 I10) |
| 601203 | 1043 | 4329847 (Myocardial inf.) | 2023-11-08 | 78203 | I21.4 | 45572081 (ICD10 I21.4) |
PROCEDURE_OCCURRENCE — les actes médicaux
- Rôle :
- Recense les gestes médicaux réalisés sur le patient : interventions chirurgicales, examens d’imagerie, gestes techniques, etc.
- Une ligne par :
- Acte enregistré.
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et aux vocabulaires (SNOMED CT côté standard, CCAM ou CPT-4 côté source selon le pays).
PROCEDURE_OCCURRENCE documente tout ce qu’on fait au patient, par opposition à ce qu’on observe chez lui (CONDITION_OCCURRENCE) ou ce qu’on lui donne (DRUG_EXPOSURE).
| Colonne | Contenu |
|---|---|
procedure_occurrence_id | Identifiant unique de l’acte |
person_id | Le patient |
procedure_concept_id | Concept standard (SNOMED CT le plus souvent) |
procedure_date, procedure_datetime | Date (et heure si disponible) de l’acte |
procedure_end_date, procedure_end_datetime | Date (et heure) de fin, pour les actes qui durent |
visit_occurrence_id, visit_detail_id | Contexte |
quantity | Nombre d’actes |
procedure_source_value | Code source (CCAM en France, CPT-4 aux US, ICD-10-PCS…) |
procedure_source_concept_id | Concept correspondant au code source |
procedure_type_concept_id | Provenance de l’enregistrement |
Aperçu de la table
Trois actes médicaux. Pour les deux premiers — l’appendicectomie de la patiente 1042 et la séance d’hémodialyse du patient 1043 — on dispose des heures précises de début et de fin (champs datetime), ce qui permet de calculer la durée de l’acte. La prise de sang de la patiente 1044, plus brève, n’a pas d’heure de fin renseignée. Le procedure_source_value conserve le code source (CCAM en France).
| procedure_occurrence_id | person_id | procedure_concept_id | procedure_datetime | procedure_end_datetime | visit_occurrence_id | procedure_source_value |
|---|---|---|---|---|---|---|
| 810501 | 1042 | 4198190 (Appendectomy) | 2022-03-15 09:30 | 2022-03-15 11:00 | 78201 | HHFA002 |
| 810502 | 1043 | 37397396 (Hemodialysis) | 2023-11-09 08:00 | 2023-11-09 12:15 | 78203 | JVJF002 |
| 810503 | 1044 | 4332170 (Venipuncture) | 2024-02-19 09:15 | NULL | 78305 | HSHF002 |
DEVICE_EXPOSURE — les dispositifs médicaux
- Rôle :
- Recense l’exposition du patient à un objet physique utilisé à des fins diagnostiques ou thérapeutiques : implants (stents, prothèses), matériel de soin (cathéters, sondes), consommables (seringues, bandages).
- Une ligne par :
- Exposition à un dispositif.
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et au vocabulaire SNOMED CT côté standard (domaine Device).
DEVICE_EXPOSURE stocke ce qu’on applique au patient quand il s’agit d’un objet physique — par opposition à un médicament (DRUG_EXPOSURE) ou à un geste (PROCEDURE_OCCURRENCE). La frontière avec PROCEDURE_OCCURRENCE peut être floue : la pose d’un stent est une procédure, mais le stent lui-même est un dispositif. Les deux tables coexistent souvent pour le même épisode de soin.
| Colonne | Contenu |
|---|---|
device_exposure_id | Identifiant unique de l’exposition |
person_id | Le patient |
device_concept_id | Concept standard (SNOMED CT, domaine Device) |
device_exposure_start_date, device_exposure_end_date | Période d’exposition |
unique_device_id, production_id | UDI (Unique Device Identifier) FDA si disponible |
quantity | Nombre de dispositifs utilisés |
visit_occurrence_id, visit_detail_id | Contexte |
device_source_value | Libellé ou code source |
device_type_concept_id | Provenance (remboursement, DPI…) |
Aperçu de la table
Trois dispositifs. Pendant son passage en réanimation, la patiente 1042 a été équipée d’un cathéter veineux central (en place pendant trois jours) et d’une sonde urinaire. Le patient 1043 a reçu un stent coronaire pendant son passage aux urgences pour infarctus — un implant, sans date de fin.
| device_exposure_id | person_id | device_concept_id | device_exposure_start_date | device_exposure_end_date | visit_occurrence_id |
|---|---|---|---|---|---|
| 115001 | 1042 | 4160023 (Central venous catheter) | 2022-03-14 | 2022-03-17 | 78201 |
| 115002 | 1042 | 4047968 (Urinary catheter) | 2022-03-14 | 2022-03-16 | 78201 |
| 115003 | 1043 | 4252356 (Coronary artery stent) | 2023-11-08 | NULL | 78203 |
NOTE — les comptes-rendus en texte libre
- Rôle :
- Capture les documents en texte libre rédigés par les soignants : comptes-rendus d’hospitalisation, courriers de consultation, observations médicales, comptes-rendus opératoires…
- Une ligne par :
- Document texte produit pour un patient.
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL,PROVIDER(l’auteur), et au vocabulaire LOINC (Document Ontology) côté standard.
NOTE accueille les données non structurées : ce que les autres tables ne capturent pas parce que c’est de la rédaction libre. C’est la matière première du TAL (NLP en anglais), dont les résultats remontent ensuite dans une table dédiée NOTE_NLP.
| Colonne | Contenu |
|---|---|
note_id | Identifiant unique du document |
person_id | Le patient |
note_date, note_datetime | Date (et heure si disponible) de rédaction |
note_class_concept_id | Classification LOINC du type de document (CR d’hospitalisation, lettre de sortie…) |
note_title | Titre du document |
note_text | Contenu intégral du document (texte) |
encoding_concept_id | Encodage des caractères (typiquement UTF-8) |
language_concept_id | Langue du document |
provider_id | Auteur du document |
visit_occurrence_id, visit_detail_id | Contexte |
note_type_concept_id | Provenance (DPI, dictée, importation…) |
Aperçu de la table
Trois notes produites pendant l’hospitalisation de la patiente 1042 : un compte-rendu d’admission rédigé aux urgences, un compte-rendu opératoire après l’appendicectomie, et une lettre de sortie. Le contenu intégral est dans note_text (tronqué ici pour l’affichage). Chaque ligne porte sa classification LOINC, qui permet de filtrer par type de document — par exemple toutes les lettres de sortie d’un service donné.
| note_id | person_id | note_date | note_class_concept_id | note_title | visit_occurrence_id |
|---|---|---|---|---|---|
| 700101 | 1042 | 2022-03-14 | 706470 (Admission note) | Observation d’entrée | 78201 |
| 700102 | 1042 | 2022-03-15 | 706526 (Operative note) | CR opératoire — appendicectomie | 78201 |
| 700103 | 1042 | 2022-03-21 | 706473 (Discharge summary) | Lettre de sortie | 78201 |
Exploiter le texte libre
Le texte brut de note_text est rarement utilisable tel quel pour une analyse : il faut le structurer. C’est le rôle du TAL (NLP en anglais) — extraction d’entités cliniques, de négations, de relations — dont les résultats vont dans NOTE_NLP, une ligne par terme extrait.
DRUG_EXPOSURE — les médicaments
- Rôle :
- Recense toutes les expositions médicamenteuses : prescriptions, dispensations en pharmacie, administrations à l’hôpital.
- Une ligne par :
- Exposition à un médicament (un même traitement chronique génère plusieurs lignes).
- Connectée à :
PERSON,VISIT_OCCURRENCE,VISIT_DETAIL, et au vocabulaire RxNorm côté standard.
DRUG_EXPOSURE regroupe toutes les expositions médicamenteuses : prescriptions, dispensations, administrations à l’hôpital. Le drug_type_concept_id permet de distinguer ces provenances.
| Colonne | Contenu |
|---|---|
drug_exposure_id | Identifiant unique |
person_id | Le patient |
drug_concept_id | Concept standard (RxNorm le plus souvent) |
drug_exposure_start_date, drug_exposure_end_date | Période d’exposition |
quantity, days_supply, dose_unit_source_value | Posologie |
route_concept_id | Voie d’administration |
drug_source_value | Libellé source |
drug_type_concept_id | Type d’enregistrement (prescription, dispensation, etc.) |
Aperçu de la table
Trois expositions médicamenteuses, de provenances différentes : une prescription de célécoxib pour la patiente 1042 à la sortie d’hospitalisation, une administration d’ibuprofène à l’hôpital le lendemain de l’appendicectomie, et une dispensation pharmacie d’un antalgique pour le patient 1043. Le drug_type_concept_id permet de distinguer ces trois cas.
| drug_exposure_id | person_id | drug_concept_id | drug_exposure_start_date | quantity | drug_type_concept_id |
|---|---|---|---|---|---|
| 920301 | 1042 | 1118084 (celecoxib) | 2022-03-15 | 30 | 32838 (prescription) |
| 920302 | 1042 | 19078461 (ibuprofen 200 mg) | 2022-03-16 | 1 | 32818 (administration) |
| 920303 | 1043 | 19133768 (paracetamol+hydrocodone) | 2023-11-10 | 20 | 32825 (dispensing) |
Calculer la dose réellement reçue
Une particularité d’OMOP : la dose de médicament prise par le patient n’est pas stockée directement dans DRUG_EXPOSURE. La colonne quantity donne seulement le nombre d’unités délivrées (comprimés, ampoules, millilitres…). Pour passer du nombre d’unités à la dose réelle en milligrammes, il faut joindre DRUG_EXPOSURE avec la table DRUG_STRENGTH, qui contient la concentration du principe actif pour chaque produit standard.
Exemple ambulatoire : un traitement sur plusieurs jours
Pour notre patiente 1042 et sa prescription de 30 comprimés de celecoxib 200 mg sur 7 jours (ligne 920301 de l’aperçu ci-dessus) :
DRUG_EXPOSURE.quantity=30(comprimés délivrés)DRUG_STRENGTH.amount_value=200(mg par comprimé pour le produit standard)DRUG_EXPOSURE.days_supply=7(jours de traitement)
→ Dose totale : 30 × 200 = 6000 mg sur la période
→ Dose journalière : 6000 ÷ 7 ≈ 857 mg/jour (soit 1,5 comprimé/jour)
Exemple hospitalier : une perfusion IV à débit variable
En contexte hospitalier, surtout en réanimation, on a souvent une ligne par administration — voire une ligne par changement de débit pour les perfusions continues. C’est très différent du modèle ambulatoire : ici, ce sont les colonnes drug_exposure_start_datetime et drug_exposure_end_datetime qui portent l’information temporelle fine, à la minute près.
Imaginons la patiente 1042 pendant son passage en réanimation (sous-séjour 91002) sous noradrénaline IV (concept 37354531, concentration 0,128 mg/mL = 128 µg/mL). Trois changements de débit sur l’après-midi :
| drug_exposure_start_datetime | drug_exposure_end_datetime | quantity (mL perfusés) |
|---|---|---|
| 2022-03-14 13:37 | 2022-03-14 14:01 | 2,0 |
| 2022-03-14 14:01 | 2022-03-14 16:20 | 27,8 |
| 2022-03-14 16:20 | 2022-03-14 18:30 | 17,3 |
Chaque ligne représente une période de débit stable (le débit n’est pas stocké tel quel — on le déduit de la quantité perfusée divisée par la durée entre start_datetime et end_datetime). La dose réellement administrée se reconstitue ensuite en multipliant le volume perfusé (quantity) par la concentration du produit (numerator_value / denominator_value dans DRUG_STRENGTH).
→ Sur la ligne du milieu (27,8 mL à 0,128 mg/mL) : 3,56 mg de noradrénaline délivrés en 2h19, soit environ 1,5 mg/h.
Pour une analyse sur tout un séjour de réanimation, il faut donc sommer toutes ces lignes par patient et par médicament, en tenant compte de la durée de chaque débit.
Quelle formule selon la forme du médicament ?
La règle de calcul change selon la forme galénique :
- Comprimé, gélule, ampoule unitaire :
quantity × amount_value - Solution, perfusion, suspension :
quantity × numerator_value / denominator_value - Patch transdermique : on utilise le débit (
numerator_valuepar unité de temps) plutôt qu’une quantité totale
Le détail des formules est dans la documentation officielle OMOP sur le calcul de dose. Nous reverrons DRUG_STRENGTH plus en détail dans l’article suivant sur les vocabulaires.
Passez à la pratique
Manipuler les données est de loin le meilleur moyen de s’approprier le modèle OMOP. Pour vous entraîner sur les tables que nous venons de détailler, nous avons préparé une série de tutoriels SQL interactifs, jouables directement dans le navigateur sur un échantillon OMOP réel — sans rien à installer :
- Niveau débutant — premiers
SELECT, premières jointures, compter des patients, filtrer par diagnostic. - Niveau intermédiaire — agrégations, fenêtres temporelles, exploitation de la dualité source/standard.
- Niveau avancé — cohortes, requêtes multi-tables complexes, calculs de dose.
Pour aller plus loin
Cet article a couvert les tables centrales pour la pratique clinique. Les autres tables (PROVIDER, CARE_SITE, LOCATION, COST, SPECIMEN, EPISODE, NOTE_NLP…) suivent les mêmes principes.
- L’explorateur interactif du schéma OMOP v5.4 donne le détail colonne par colonne de toutes les tables.
- Le chapitre 4 du Book of OHDSI est la documentation officielle complète.
- Les conventions précises (formats de date, contraintes, valeurs autorisées) sont décrites dans Themis, le référentiel officiel des conventions ETL d’OHDSI.
- OMOP CDM est un modèle relationnel d'environ 40 tables, réparties en six catégories. La v5.4 est stable depuis 2021.
- Trois conventions structurent tout le modèle : centré patient (person_id + date partout), dualité source/standard (concept_id vs source_value vs source_concept_id), et type_concept_id pour tracer la provenance de l'enregistrement.
- concept_id = 0 signale un code source non mappé. C'est l'indicateur de qualité le plus simple à surveiller en premier.
- PERSON est le point d'ancrage de tout le modèle ; VISIT_OCCURRENCE orchestre les contacts avec le système de soins ; VISIT_DETAIL capture les passages par unité (réa, médecine…).
- Sept tables pour les événements cliniques, une par domaine : CONDITION_OCCURRENCE (diagnostics), DRUG_EXPOSURE (médicaments), PROCEDURE_OCCURRENCE (actes), MEASUREMENT (valeurs quantifiables), OBSERVATION (faits cliniques sans valeur naturelle), DEVICE_EXPOSURE (dispositifs médicaux) et NOTE (texte libre).
- La dose réellement administrée n'est pas stockée dans DRUG_EXPOSURE : il faut joindre avec DRUG_STRENGTH.
- Le détail colonne par colonne est dans l'explorateur interactif ; les conventions précises (dates, contraintes, valeurs autorisées) dans Themis. Et surtout : passez à la pratique avec les tutoriels SQL pour vraiment s'approprier le modèle.