Operator Syntax Examples
The following sub-sections illustrate various AQL operators with examples.
matches
The following examples show how the ADL matches operator may be used within AQL statements.
the ADL expressions on the right-hand side of the matches operator are in ADL 1.4 format.
|
Scenario: Get all blood glucose values and their corresponding subject ids, where blood glucose > 11 mmol/L or blood glucose >= 200 mg/dL
SELECT
e/ehr_status/subject/external_ref/id/value,
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value
FROM EHR e CONTAINS COMPOSITION c
CONTAINS OBSERVATION o [openEHR-EHR-OBSERVATION.laboratory-glucose.v1]
WHERE
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value matches {
C_DV_QUANTITY<
list = <
["1"] = <
units = <"mmol/L">
magnitude = <|>=11|>
>
["2"] = <
units=<"mg/dL">
magnitude=<|>=200|>
>
>
>
}
SELECT
e/ehr_status/subject/external_ref/id/value as subjectId,
a/items[at0001]/value as analyteName,
a/items[at0001]/value as analyteResult
FROM EHR e
CONTAINS COMPOSITION c
CONTAINS OBSERVATION o[openEHR-EHR-OBSERVATION.laboratory_test_result.v1]
CONTAINS CLUSTER a[openEHR-EHR-CLUSTER.laboratory_test_analyte.v1]
WHERE
(a/items[at0001]/value/defining_code/code_string matches {'14743-9','2345-7'} AND a/items[at0001]/value/defining_code/terminology_id = 'LOINC')
AND
((a/items[at0024]/value/magnitude > 11 AND a/items[at0024]/value/units matches {'mmol/L'})
OR (a/items[at0024]/value/magnitude >= 200 AND a/items[at0024]/value/units matches {'mg/dL'}))
Scenario: Get all blood glucose values and their corresponding ehr ids, where blood glucose level is between 5-6 mmol/L or between 90-110 mg/dL
SELECT
e/ehr_id,
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value
EHR e CONTAINS COMPOSITION c
CONTAINS OBSERVATION o [openEHR-EHR-OBSERVATION.laboratory-glucose.v1]
WHERE
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value matches {
C_DV_QUANTITY<
list = <
["1"] = <
units = <"mmol/L">
magnitude = <|5.0..6.0|>
>
["2"] = <
units = <"mg/dL">
magnitude = <|90..110|>
>
>
>
}
Alternative
SELECT
e/ehr_id/value as ehrId,
a/items[at0001]/value as analyteName,
a/items[at0001]/value as analyteResult
FROM EHR e
CONTAINS COMPOSITION c
CONTAINS OBSERVATION o[openEHR-EHR-OBSERVATION.laboratory_test_result.v1]
CONTAINS CLUSTER a[openEHR-EHR-CLUSTER.laboratory_test_analyte.v1]
WHERE
(a/items[at0001]/value/defining_code/code_string matches {'14743-9','2345-7'} AND a/items[at0001]/value/defining_code/terminology_id = 'LOINC')
AND
((a/items[at0024]/value/magnitude >= 5 AND a/items[at0024]/value/magnitude <=6 AND a/items[at0024]/value/units matches {'mmol/L'})
OR (a/items[at0024]/value/magnitude >= 90 AND a/items[at0024]/value/magnitude >= 110 AND a/items[at0024]/value/units matches {'mg/dL'}))
Scenario: HbA1c > 7.0%
SELECT
e/ehr_id,
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value
EHR e CONTAINS COMPOSITION c
CONTAINS OBSERVATION o [openEHR-EHR-OBSERVATION.laboratory-glucose.v1]
WHERE
o/data[at0001]/events[at0002 and name/value='Any event']/data[at0003]/items[at0013.1]/value matches {
DV_PROPORTION matches {
numerator matches {|>7.0|}
denominator matches {|100.0|}
}
}
Alternative
SELECT
e/ehr_id/value as ehrId,
p/data[at0001]/events[at0002]/data[at0003]/items[at0006]/value as spo2Numerator
FROM EHR e
CONTAINS COMPOSITION c
CONTAINS OBSERVATION p[openEHR-EHR-OBSERVATION.pulse_oximetry.v1]
WHERE
p/data[at0001]/events[at0002]/data[at0003]/items[at0006]/value/numerator <= 96
Scenario: Total cholesterol >= 5.0 mmol/L or LDL-C >= 3.0 mmol/L
SELECT
e/ehr_id,
o/data[at0001]/events[at0002]/data[at0003]/items[at0013.1] AS TotalC,
o/data[at0001]/events[at0002]/data[at0003]/items[at0011.1, 'Fractions']/items[at0013.4, 'LDL-Cholesterol'] AS LDLC
EHR e CONTAINS COMPOSITION c
CONTAINS OBSERVATION o [openEHR-EHR-OBSERVATION.laboratory-hba1c.v1]
WHERE
o/data[at0001]/events[at0002, 'Any event']/data[at0003]/items[at0013.1]/value matches {
DV_QUANTITY matches {
units matches {"mmol/L"}
magnitude matches {|>=5.0|}
}
}
OR
o/data[at0001]/events[at0002]/data[at0003]/items[at0011.1, 'Fractions']/items[at0013.4, 'LDL-Cholesterol']/value matches {
DV_QUANTITY matches {
units matches {"mmol/L"}
magnitude matches {|>=3.0|}
}
}
Arithmetic operators
The following example shows how arithmetic operators may be used within AQL statements.
Scenario: For each recorded administration of ampicillin check for problem diagnosis of skin rash that is within 2 days of the administration date
SELECT e/ehr_id
FROM EHR e CONTAINS (COMPOSITION c1
CONTAINS ACTION a [openEHR-EHR-ACTION.medication.v1]
CONTAINS ITEM_TREE it [openEHR-EHR-ITEM_TREE.medication.v1]) AND
CONTAINS (COMPOSITION c2 CONTAINS EVALUATION eval [openEHR-EHR-EVALUATION.problem-diagnosis.v1])
WHERE
it/description[openEHR-EHR-ITEM_TREE.medication.v1]/items[at0001]/value matches {"SNOMED::31087008"} AND
eval/data[at0001]/items[at0002.1]/value/value/defining_code matches {
CODE_PHRASE matches {[SNOMED::294506009, 21626009]}
} AND
eval/data[at0001]/items[at0010]/value - it/description[openEHR-EHR-ITEM_TREE.medication.v1]/items[at0018]/items[at0019]/value matches {
DV_DURATION matches {
value matches{<=P2d}
}
}
Nest Query and 'Not in'
The following example shows the use of a nested query and the not-in operator.
Scenario: All patients who have not been discharged
SELECT e/ehr_id
FROM
EHR e CONTAINS
ADMIN_ENTRY ae1 [openEHR-EHR-ADMIN_ENTRY.admission.v1]
WHERE
ae1/encounter_id/value not in (
SELECT ae2/encounter_id/value
FROM
EHR e CONTAINS
ADMIN_ENTRY ae2 [openEHR-EHR-ADMIN_ENTRY.discharge.v1]
)
Function Syntax Examples
The following sub-sections illustrate various AQL functions with examples.
Aggregate functions
Example 1: The
COUNT() and MIN() functions are used to return the number of discharge letters and the date of their oldest event:SELECT
count(*) AS counter, min(c/context/start_time) as firstTime
FROM
EHR [ehr_id/value=$ehrUid]
CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.administrative_encounter.v1]
CONTAINS ADMIN_ENTRY [openEHR-EHR-ADMIN_ENTRY.admission.v1]
Example 2: The
COUNT() function is used to return a counter of all distinct test analyte names for a given EHR:SELECT
COUNT(DISTINCT a/items[at0001]/value) AS counter
FROM
EHR [ehr_id/value=$ehrUid]
CONTAINS COMPOSITION c
CONTAINS OBSERVATION [openEHR-EHR-OBSERVATION.laboratory_test_result.v1]
CONTAINS CLUSTER a[openEHR-EHR-CLUSTER.laboratory_test_analyte.v1]
Example 3: Using
MIN(), MAX() and AVG() functions to determine edge and mean values for systolic blood pressure:SELECT
MAX(o/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude) AS maxValue,
MIN(o/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude) AS minValue,
AVG(o/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude) AS meanValue
FROM
EHR e CONTAINS COMPOSITION c[openEHR-EHR-COMPOSITION.encounter.v1]
CONTAINS OBSERVATION o[openEHR-EHR-OBSERVATION.blood_pressure.v1]
TERMINOLOGY
The following are examples of the use of TERMINOLOGY function related to FHIR terminology operations.
Example 1: Expand a value set
WHERE
e/value/defining_code/code_string matches TERMINOLOGY('expand', 'hl7.org/fhir/r4', 'url=http://snomed.info/sct?fhir_vs=isa/50697003')
Example 2: Validate a code in a value set
WHERE
TERMINOLOGY('validate', 'hl7.org/fhir/r4', 'system=http://snomed.info/sct&code=122298005&url=http://snomed.info/sct?fhir_vs&display=Astrovirus RNA assay') = true
Example 3: Look-up a code
WHERE
e/value/defining_code/code_string matches TERMINOLOGY('lookup', 'hl7.org/fhir/r4', 'system=http://loinc.org&code=1963-8')
Example 4: Map a code
WHERE
e/value/defining_code/code_string matches TERMINOLOGY('map', 'hl7.org/fhir/r4', 'system=http://hl7.org/fhir/composition-status&code=preliminary&source=http://hl7.org/fhir/ValueSet/composition-status&target=http://hl7.org/fhir/ValueSet/v3-ActStatus')
Example 5: Subsumption testing
WHERE
TERMINOLOGY('subsumes', 'hl7.org/fhir/r4', CONCAT('system=http://snomed.info/sct&codeA=235856003&codeB=', e/value/defining_code/code_string)) = true