CQL WorkbenchDocs
Docs contents
CQL primer

Reading the workbench’s CQL

Follow one NHI reimbursement clause through the CQL the workbench exports: what each part does, and how the result comes out when data is missing. No programming experience needed.

What CQL is: Clinical Quality Language, the HL7 standard for writing clinical rules. The workbench uses only a small part of it, and this page covers only that part.

The example clause

Every example on this page uses this clause. The workbench splits it into four atomic conditions and two groups:

本品限內科專科醫師處方,病人需為成人(年滿十八歲),且 eGFR ≥ 30 mL/min/1.73m²;未達標準者,須經腎臟科會診同意後使用。Translation: Must be prescribed by an internal medicine specialist. The patient must be an adult (18 or older) with eGFR ≥ 30 mL/min/1.73m². Below that threshold, use requires nephrology consultation approval.
IDMeaning
C1Prescriber is an internal medicine specialist
C2Patient is 18 or older
C3eGFR ≥ 30 mL/min/1.73m²
C4Nephrology consultation approved
G2C3 or C4 (any one)
G1C1, C2 and G2 (all; the verdict for the whole clause)

The full file

This is the complete file renderCql generates for the clause. The next four sections walk through it from top to bottom.

Clause_Sample.cql40 lines
library Clause_Sample version '1.0.0'

using FHIR version '4.0.1'

/* Evidence adapters supply true, false, or null for each reviewed criterion. */
parameter "C1" Boolean default null
parameter "C2" Boolean default null
parameter "C3" Boolean default null
parameter "C4" Boolean default null

context Patient

define "Criterion C1":
  "C1"

define "Criterion C2":
  "C2"

define "Criterion C3":
  "C3"

define "Criterion C4":
  "C4"

define "Group G1":
  "Criterion C1"
  and "Criterion C2"
  and "Group G2"

define "Group G2":
  "Criterion C3"
  or "Criterion C4"

define "Eligibility":
  "Group G1"

define "Eligibility Status":
  if "Eligibility" is true then 'eligible'
  else if "Eligibility" is false then 'ineligible'
  else 'insufficient-data'

Lines 1, 3 and 11 say what the file is, which data model it uses, and who it is evaluated for.

library Clause_Sample version '1.0.0'
The name and version of this logic, used to tell exported files apart.
using FHIR version '4.0.1'
Declares the FHIR R4 data model. The workbench’s logic doesn’t actually read FHIR data; the next section explains why.
context Patient
Every define after this line is evaluated for one patient.

Parameters: one input per condition

Each atomic condition becomes a parameter of type Boolean. The CQL never queries the record itself: an evidence adapter checks the record first and passes the answer in as a parameter.

parameter "C3" Boolean default null

A parameter only ever holds one of three values. Take C3 (eGFR ≥ 30):

trueFound, and it meets the conditionThe latest eGFR is 42.
falseFound, but it doesn’tThe latest eGFR is 25.
nullNot foundThe record has no eGFR result.

default null means that when nobody supplies a value, the answer is “unknown”, not “doesn’t meet”.

define: naming an expression

define is followed by a name and a colon; its body starts on the next line. The workbench generates three layers:

define "Criterion C3":
  "C3"

define "Group G2":
  "Criterion C3"
  or "Criterion C4"

define "Eligibility":
  "Group G1"
  • Criterion C3 takes the value of parameter C3 as is.
  • Group G2 is G2 on the review screen: C3 or C4.
  • Eligibility points at the outermost group, G1: the verdict for the whole clause.

Note: double quotes hold names, like "Group G2"; single quotes hold text, like 'eligible'.

Three-valued logic: what null does

A parameter can be null, so and, or and not all have to handle “unknown”. The rule fits in one sentence: if the answer is already settled, null doesn’t matter; if it isn’t, the result is null.

andtruefalsenull
truetruefalsenull
falsefalsefalsefalse
nullnullfalsenull
ortruefalsenull
truetruetruetrue
falsetruefalsenull
nulltruenullnull
notResult
truefalse
falsetrue
nullnull

For example, false and null is false: once one condition fails, “all of them” can’t hold, whatever the other value is. true or null is true for the same reason.

The result: why is true

The last define turns the three-valued result into three statuses:

define "Eligibility Status":
  if "Eligibility" is true then 'eligible'
  else if "Eligibility" is false then 'ineligible'
  else 'insufficient-data'

is true holds only when the value is true. On null it returns false, not null, so the three branches map exactly to the three outcomes: eligible, ineligible and insufficient-data.

Don’t write it this way: when the condition of a CQL if is null, it takes the else branch, so a patient with missing data would be marked ineligible.

define "Eligibility Status":
  if "Eligibility" then 'eligible'
  else 'ineligible'

Four scenarios, step by step

Plug in each set of parameters and work from the inside out: G2 first, then G1.

ScenarioC1C2C3C4G2G1Result
eGFR meets thresholdtruetruetruefalsetruetrueeligible
Under 18truefalsetruetruetruefalseineligible
No eGFR, consult approvedtruetruenulltruetruetrueeligible
No eGFR, no consult recordtruetruenullnullnullnullinsufficient-data

In row three C3 is null, but C4 is true, and null or true is already settled as true, so the patient is still eligible. In row four both C3 and C4 are null, so G2 can’t be decided and the whole clause is insufficient-data until an eGFR result or a consult record comes in.

Try it yourself

Set each condition to meets, doesn’t meet or not found, and watch G2, G1 and the result change. Start from a scenario in the table above, then change one cell.

Load a scenario from the table:
  • C1Prescriber is an internal medicine specialist
  • C2Patient is 18 or older
  • C3eGFR ≥ 30 mL/min/1.73m²
  • C4Nephrology consultation approved

G2=C3orC4=nullortrue→true

One side is true, which settles the or as true; the null on the other side doesn’t matter.

G1=C1andC2andG2=trueandtrueandtrue→true

All three are true.

Eligibility Status →'eligible'Eligible

Eligibility is true, so the first branch applies.

FAQ

What is CQL?

CQL (Clinical Quality Language) is an HL7 standard for writing clinical rules, such as reimbursement criteria, quality measures and clinical decision support, in a syntax close to English. The same CQL file can be run by a computer and read by clinicians and reviewers.

How does CQL relate to FHIR?

CQL describes logic and is not tied to a data format; paired with FHIR, CQL can read values straight from FHIR health records. The CQL that CQL Workbench generates does not query FHIR itself: an evidence adapter checks the record first and passes in true, false or null for each condition as a parameter.

What is the difference between CQL and ELM?

CQL is the syntax people read and write; ELM (Expression Logical Model) is the structured form CQL compiles to, which execution engines run. CQL Workbench compiles CQL to ELM with cql-engine, then checks the result of every scenario.

Can I learn CQL without a programming background?

Yes. The CQL the workbench generates uses only a small part of the language: parameters, define, and, or, not and if. This page walks through one NHI reimbursement clause from start to finish, after which you can read the exported files.

Why write NHI reimbursement rules in CQL?

A written clause has to be interpreted by a person, and two people can read it differently. Written in CQL, the same record always gets the same result, and missing data is reported as insufficient data instead of quietly counting as ineligible.

Next steps