SQL on FHIR WG Meetings

FHIR-to-OMOP in miniature — one Condition, three possible tables, terminology decides which — May 26, 2026

Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai
Arjun Sanyal
Arjun Sanyal
Principal Antidote Solutions
Steve Munini
Steve Munini
CEO and CTO, Helios Software
May 26, 2026

A work-in-progress FHIR-to-OMOP mapping — built out of SQL on FHIR pieces

  • A FHIR profile that guarantees a conforming resource is translatable
  • Value sets reverse-engineered out of the OMOP Athena tables
  • Concept maps for the small mappings like status and gender
  • A ViewDefinition to flatten
  • A SQL query to join it all together

Nikolai also announced he was abandoning his first approach — diffing his output against the official Synthea-to-OMOP ETL — because that ETL is wrong in enough places that it isn't a ground truth. Hand-written test cases replace it.

The Condition walkthrough — the whole problem in miniature

OMOP's condition_occurrence wants a SNOMED concept ID, but your Condition might be coded in ICD-10, so you look the code up in Athena's mapping tables.

  • One ICD-10 code can map to several SNOMED codes → several rows
  • Then check the domain of the concept you landed on: if it's a condition it goes to condition_occurrence, if it's an observation or a measurement it goes somewhere else entirely, with different fields

In SQL that whole decision is a join against the terminology tables — which is also why it stays fast over millions of rows.

Arjun — this isn't type X to type Y

Arjun Sanyal
Arjun Sanyal
Principal Antidote Solutions

This isn't type X to type Y, because both the type and the cardinality change. Plenty of ICD-10 codes aren't diagnoses at all — a BMI is an observation — and some are two conditions bundled into one code, which you can never map cleanly into a more precise system, because the more precise system asks for information the source never had.

Nikolai — why SQL, not a mapping language

Nikolai Ryzhikov
Nikolai Ryzhikov
CTO at Health Samurai

The logic is genuinely procedural: look up the default vocabulary, split if the mapping is one-to-many, check the domain, then apply a different transformation depending on the answer. I don't think that's expressible in FHIR Mapping Language without reaching for something else.

Even if translate could carry it, it wouldn't survive bulk transformation — people would burn CPUs. In SQL it's a join.

Steve — spec inconsistencies from implementing operation-by-operation

Had them clarified before filing:

  • The binary-versus-raw-payload question — Nikolai conceded this is an official hack, recommended by Gino, and that FHIR core probably needs an issue about it
  • Whether a Bundle passed in should be unwrapped
  • The return shape diverging between $viewdefinition-run and $sqlquery-run
  • Streaming guidance that only exists on one operation

Nikolai's line on all of them: if we said it once, it should be said everywhere it applies.