讀懂工作台的 CQL
用一條健保給付條文,從頭看完工作台匯出的 CQL:每一段在做什麼,缺資料時結果又怎麼算。不需要寫過程式。
CQL 是什麼:Clinical Quality Language(臨床品質語言),HL7 制定、用來寫臨床規則的標準語言。工作台只用到其中一小部分語法,這頁只講這一部分。
範例條文
整頁都用這一條。工作台把它拆成四個原子條件和兩個群組:
本品限內科專科醫師處方,病人需為成人(年滿十八歲),且 eGFR ≥ 30 mL/min/1.73m²;未達標準者,須經腎臟科會診同意後使用。
| 代號 | 內容 |
|---|---|
| C1 | 處方醫師為內科專科醫師 |
| C2 | 病人年滿 18 歲 |
| C3 | eGFR ≥ 30 mL/min/1.73m² |
| C4 | 經腎臟科會診同意 |
| G2 | C3、C4 任一符合 |
| G1 | C1、C2、G2 全部符合(整條條文的判斷) |
完整的 CQL
這是 renderCql 為這條條文產生的完整檔案。接下來四節由上往下,一段一段說明。
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'標頭:library、using、context
第 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)為例:
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。
| and | true | false | null |
|---|---|---|---|
| true | true | false | null |
| false | false | false | false |
| null | null | false | null |
| or | true | false | null |
|---|---|---|---|
| true | true | true | true |
| false | true | false | null |
| null | true | null | null |
| not | 結果 |
|---|---|
| true | false |
| false | true |
| null | null |
例如 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。
| 情境 | C1 | C2 | C3 | C4 | G2 | G1 | 結果 |
|---|---|---|---|---|---|---|---|
| eGFR 達標 | true | true | true | false | true | true | eligible |
| 未成年 | true | false | true | true | true | false | ineligible |
| 無 eGFR,有會診 | true | true | null | true | true | true | eligible |
| 無 eGFR,無會診紀錄 | true | true | null | null | null | null | insufficient-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 之後,同一份病歷每次都會得到同樣的結果;資料不足時也會明確標成資料不足,而不是默默判成不符合。