Archetype Query Language Examples
Issuer: openEHR Specification Program | |
---|---|
Release: QUERY Release-1.1.0 |
Status: DEVELOPMENT |
Revision: [latest_issue] |
Date: [latest_issue_date] |
Keywords: query, AQL, example, openehr |
© 2020 - 2021 The openEHR Foundation | |
---|---|
The openEHR Foundation is an independent, non-profit foundation, facilitating the sharing of health records by consumers and clinicians via open specifications, clinical models and open platform implementations. |
|
Licence |
Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/ |
Support |
Issues: Problem Reports |
Amendment Record
Issue | Details | Raiser | Completed |
---|---|---|---|
Release 1.1.0 |
|||
SPECQUERY-8 Improve readability and clean up text (non-semantic). |
S Iancu |
||
SPECQUERY-12 Improve terminology support by adding a new TERMINOLOGY function. |
L Marco-Ruiz, |
24 Nov 2020 |
|
SPECQUERY-31 Move AQL examples to a new separate specification. |
openEHR SEC |
09 Nov 2020 |
Acknowledgements
Contributors
This specification benefited from wide formal and informal input from the openEHR and wider health informatics community. The openEHR Foundation would like to recognise the following people for their contributions.
-
Heath Frankel, Ocean Health Systems, Australia
-
Ian McNicoll MD, FreshEHR, UK
-
Luiz Marco-Ruiz, PhD, Norwegian Centre for E-health Research, Norway
-
Sebastian Iancu, Architect, Code24, Netherlands
-
Thomas Beale, Ars Semantica UK, openEHR Foundation Management Board
1. Preface
1.2. Status
This specification is in the DEVELOPMENT state. The latest development version of this document can be found at https://specifications.openehr.org/releases/QUERY/latest/AQL_examples.html.
Known omissions or questions are indicated in the text with a 'to be determined' paragraph, as follows:
TBD: (example To Be Determined paragraph)
1.3. Tools
Various tools that can be used to work with archetypes and templates, including extracting 'archetype paths' for use in AQL statements, are listed on the openEHR website modelling tools page.
1.4. Feedback
Feedback may be provided on the openEHR AQL forum.
Issues may be raised on the specifications Problem Report tracker.
To see changes made due to previously reported issues, see the QUERY component Change Request tracker.
1.5. Original Source
The original text of this document was taken from the openEHR AQL specification.
2. Overview
Archetype Query Language (AQL) is a declarative query language developed specifically for expressing queries used for searching and retrieving the data found in archetype-based repositories.
This document provides AQL syntax examples as well as example of use of AQL in various complex scenarios, for both single-subject and population queries.
These examples mostly relate to the openEHR Reference Model (RM) and the openEHR clinical archetypes, but the syntax is independent of information model, application, programming language, system environment, and storage model.
2.1. Operator Syntax Examples
The following sub-sections illustrate various AQL operators with examples.
2.1.1. matches
The following examples show how the ADL matches
operator may be used within AQL statements.
Note
|
the ADL expressions on the right-hand side of the matches operator are in ADL 1.4 format.
|
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'}))
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|> > > > }
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'}))
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|} } }
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
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|} } }
2.1.2. Arithmetic operators
The following example shows how arithmetic operators may be used within AQL statements.
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} } }
2.1.3. Nest Query and 'Not in'
The following example shows the use of a nested query and the not-in
operator.
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] )
2.2. Function Syntax Examples
The following sub-sections illustrate various AQL functions with examples.
2.2.1. Aggregate functions
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]
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]
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]
2.2.2. TERMINOLOGY
The following are examples of the use of TERMINOLOGY
function related to FHIR terminology operations.
WHERE e/value/defining_code/code_string matches TERMINOLOGY('expand', 'hl7.org/fhir/r4', 'url=http://snomed.info/sct?fhir_vs=isa/50697003')
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
WHERE e/value/defining_code/code_string matches TERMINOLOGY('lookup', 'hl7.org/fhir/r4', 'system=http://loinc.org&code=1963-8')
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')
WHERE TERMINOLOGY('subsumes', 'hl7.org/fhir/r4', CONCAT('system=http://snomed.info/sct&codeA=235856003&codeB=', e/value/defining_code/code_string)) = true
3. Single-Subject AQL Examples
SELECT obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude AS systolic, obs/data[at0001]/events[at0006]/data[at0003]/items[at0005]/value/magnitude AS diastlic, c/context/start_time AS date_time FROM EHR [ehr_id/value=$ehrUid] CONTAINS COMPOSITION c [openEHR-EHR-COMPOSITION.encounter.v1] CONTAINS OBSERVATION obs [openEHR-EHR-OBSERVATION.blood_pressure.v1] WHERE obs/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value/magnitude >= 140 OR obs/data[at0001]/events[at0006]/data[at0003]/items[at0005]/value/magnitude >= 90 ORDER BY c/context/start_time DESC LIMIT 5