Compiling CQL into SQL — and why writing measures one patient at a time is what makes them slow — Jul 7, 2026
Evan — CQL and SQL are both relational algebra
CQL and SQL are both ways of writing relational algebra, so one translates into the other mechanically.
His pipeline: CQL → relational algebra → ViewDefinition → whatever SQL dialect you want, with the CQL-specific quirks patched in last so each dialect's own features can still be used.
Why not go straight from ELM to SQL?
It fails: emitting any given piece of SQL keeps needing context from somewhere else in the tree. The algebra layer exists so you can see the whole query before you write a line of it.
The scaling problem has a specific cause
A measure written in context Patient answers true or false for one patient, so you run it a patient at a time.
context Unfiltered drops the implicit patient join — from Condition then means every condition for everyone, and the numerator comes back as a list of patient IDs.
Any measure can be converted automatically.
One-at-a-time should never have been the default.
Early numbers on DuckDB
Single-digit microseconds per bundle, roughly a million members a second, against an industry target of about a millisecond per member on CQL engines.
AI translation — fine for simple, falls apart on hard
CQL's date and interval rules are subtle enough that the model ping-pongs between getting the general case right and getting the edge cases right.
If you are going the AI route you may as well skip CQL and translate from the written spec.