CQL Workbench文件
文件目錄
CQL 入門

讀懂工作台的 CQL

用一條健保給付條文,從頭看完工作台匯出的 CQL:每一段在做什麼,缺資料時結果又怎麼算。不需要寫過程式。

CQL 是什麼:Clinical Quality Language(臨床品質語言),HL7 制定、用來寫臨床規則的標準語言。工作台只用到其中一小部分語法,這頁只講這一部分。

範例條文

整頁都用這一條。工作台把它拆成四個原子條件和兩個群組:

本品限內科專科醫師處方,病人需為成人(年滿十八歲),且 eGFR ≥ 30 mL/min/1.73m²;未達標準者,須經腎臟科會診同意後使用。
代號內容
C1處方醫師為內科專科醫師
C2病人年滿 18 歲
C3eGFR ≥ 30 mL/min/1.73m²
C4經腎臟科會診同意
G2C3、C4 任一符合
G1C1、C2、G2 全部符合(整條條文的判斷)

完整的 CQL

這是 renderCql 為這條條文產生的完整檔案。接下來四節由上往下,一段一段說明。

Clause_Sample.cql40 行
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'

第 1、3、11 行說明這份檔案是什麼、用什麼資料模型、替誰計算。

library Clause_Sample version '1.0.0'
這份邏輯的名稱和版本號,匯出後靠它辨認是哪一份。
using FHIR version '4.0.1'
宣告資料模型是 FHIR R4。工作台的邏輯其實不直接讀 FHIR 資料,原因在下一節。
context Patient
這行之後的每個 define,都是針對一位病人計算。

參數:每個條件一個輸入

每個原子條件對應一個 parameter,型別是 Boolean。CQL 本身不查病歷:證據轉接器(evidence adapter)先查好,再把答案當成參數傳進來。

parameter "C3" Boolean default null

每個參數只會是下面三種值之一,以 C3(eGFR ≥ 30)為例:

true查到,而且符合最近一次 eGFR 是 42。
false查到,但不符合最近一次 eGFR 是 25。
null查不到病歷裡沒有 eGFR 檢驗。

default null 的意思是:沒有人提供值的時候,就當作「不知道」,而不是「不符合」。

define:替一段運算取名字

define 後面接名稱和冒號,下一行開始是它的內容。工作台產生三層 define:

define "Criterion C3":
  "C3"

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

define "Eligibility":
  "Group G1"
  • Criterion C3 直接取參數 C3 的值。
  • Group G2 就是審核畫面上的 G2:C3 或 C4 任一符合。
  • Eligibility 指向最外層的 G1,也就是整條條文的判斷。

小提醒:雙引號包的是名稱,例如 "Group G2";單引號包的是文字,例如 'eligible'。

三值邏輯:遇到 null 怎麼算

參數可能是 null,所以 and、or、not 都要處理「不知道」。規則只有一句:答案已經確定,就不管 null;還不確定,結果就是 null。

andtruefalsenull
truetruefalsenull
falsefalsefalsefalse
nullnullfalsenull
ortruefalsenull
truetruetruetrue
falsetruefalsenull
nulltruenullnull
not結果
truefalse
falsetrue
nullnull

例如 false and null 是 false:只要有一個條件不符合,「全部符合」就不可能成立,另一個是什麼都一樣。true or null 是 true,道理相同。

結果:為什麼寫 is true

最後一個 define 把三值結果轉成三種狀態:

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

is true 只在值是 true 時成立;遇到 null 會得到 false,而不是 null。所以三個分支剛好對應三種結果:符合、不符合、資料不足。

不要這樣寫:CQL 的 if 遇到 null 條件會走 else,資料不足的病人就會被判成 ineligible。

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

四種情境走一遍

把四組參數帶進去,由內往外算:先算 G2,再算 G1。

情境C1C2C3C4G2G1結果
eGFR 達標truetruetruefalsetruetrueeligible
未成年truefalsetruetruetruefalseineligible
無 eGFR,有會診truetruenulltruetruetrueeligible
無 eGFR,無會診紀錄truetruenullnullnullnullinsufficient-data

第三列的 C3 是 null,但 C4 是 true,null or true 已經確定是 true,所以仍然符合。第四列的 C3、C4 都是 null,G2 無法確定,整條就是資料不足,要等補上 eGFR 或會診紀錄再算。

自己試試看

把每個條件切成符合、不符合或查不到,看 G2、G1 和最後的結果怎麼跟著變。可以先套用上表的情境,再改其中一格。

套用上表的情境:
  • C1處方醫師為內科專科醫師
  • C2病人年滿 18 歲
  • C3eGFR ≥ 30 mL/min/1.73m²
  • C4經腎臟科會診同意

G2=C3orC4=nullortrue→true

有一個是 true,or 就確定是 true,另一個是 null 也不影響。

G1=C1andC2andG2=trueandtrueandtrue→true

三項全部是 true。

Eligibility Status →'eligible'符合

Eligibility 是 true,走第一個分支。

常見問題

CQL 是什麼?

CQL(Clinical Quality Language,臨床品質語言)是 HL7 制定的標準語言,用接近英文的語法寫臨床規則,例如給付條件、品質指標與臨床決策支援。同一份 CQL 可以交給電腦執行,醫師與審查人員也讀得懂。

CQL 和 FHIR 有什麼關係?

CQL 只描述邏輯,不綁定資料格式;搭配 FHIR 時,CQL 可以直接從 FHIR 病歷資料取值。CQL Workbench 產生的 CQL 不直接查 FHIR,而是由證據轉接器先查好,再把每個條件的 true、false 或 null 當成參數傳進來。

CQL 和 ELM 有什麼不同?

CQL 是給人讀寫的語法;ELM(Expression Logical Model)是 CQL 編譯後的結構化格式,給執行引擎使用。CQL Workbench 用 cql-engine 把 CQL 編譯成 ELM,再逐一驗證每個情境的結果。

不會寫程式,可以學 CQL 嗎?

可以。工作台產生的 CQL 只用到一小部分語法:參數、define、and、or、not 和 if。這頁用一條健保給付條文從頭走一遍,看完就能讀懂匯出的檔案。

為什麼要把健保給付規則寫成 CQL?

文字條文要靠人逐條判讀,結果可能因人而異。寫成 CQL 之後,同一份病歷每次都會得到同樣的結果;資料不足時也會明確標成資料不足,而不是默默判成不符合。

下一步