AQL
Introduction
AQL is a SQL-like language tailored for openEHR data.
This document describes the AQL dialect supported by this system and how to write effective queries against EHR content and demographics data. After reading this document, you should be able to write queries that:
- Select data from EHR content and demographics
- Filter and sort data
- Perform aggregations
- Use functions
- Use parameters
- Use wildcards and set membership
- Use LIMIT and OFFSET
AQL support is under development. It contains some experimental features and may change in the future.
Basics
Selecting data
Selecting data is done using the SELECT clause and a FROM tree. The SELECT clause specifies the columns to be returned and the FROM tree specifies the data sources to be queried.
Query syntax
SELECT [DISTINCT] <column list>
Examples
SELECT * FROM EHRSELECT e FROM EHR eSELECT e/ehr_id FROM EHR eSELECT c/uid/value, c/name/value FROM COMPOSITION cSELECT MAX(c/time_created) FROM COMPOSITION cSELECT DISTINCT c/archetype_node_id FROM COMPOSITIONSELECT COUNT(*) FROM EHR
FROM tree
The FROM tree specifies the data sources to be queried. The FROM tree consists of a list of sources, each of which can be a composition, a version, a person, an organisation, a group, or an EHR.
Query syntax
FROM <source> [AS <alias>]? [CONTAINS <source> [AS <alias>]? [AND | OR]? ...
Examples
SELECT * FROM EHR eSELECT * FROM EHR e CONTAINS COMPOSITION cSELECT * FROM EHR e CONTAINS COMPOSITION c CONTAINS OBSERVATION oSELECT * FROM EHR e CONTAINS (COMPOSITION c CONTAINS OBSERVATION o OR EVALUATION v)SELECT * FROM EHR e CONTAINS (COMPOSITION c CONTAINS OBSERVATION o AND EVALUATION v)SELECT * FROM EHR e CONTAINS (COMPOSITION c CONTAINS OBSERVATION o AND (EVALUATION v CONTAINS CLUSTER cl)SELECT * FROM EHR e CONTAINS (EHR_STATUS es AND CONTAINS COMPOSITION c CONTAINS OBSERVATION o)
WHERE clause
The WHERE clause specifies the conditions to be applied to the data sources.
Query syntax
WHERE <predicate>
Examples
SELECT * FROM EHR e WHERE e/ehr_id/value = '...'SELECT * FROM EHR e WHERE e/ehr_status/state = 'active'SELECT * FROM EHR e WHERE e/ehr_id/value = '...' AND e/ehr_status/state = 'active' OR e/ehr_status/state = 'suspended'SELECT * FROM EHR e WHERE e/ehr_id/value = '...' AND e/ehr_status/state = 'active' OR e/ehr_status/state = 'suspended' AND e/ehr_status/last_change_time > '2021-12-21T15:19:31.649+01:00'
ORDER BY clause
The ORDER BY clause specifies the order in which the results should be returned.
Query syntax
ORDER BY <column> [ASC | DESC]
Examples
SELECT * FROM EHR e ORDER BY e/ehr_id/value ASCSELECT * FROM EHR e ORDER BY e/ehr_id/value DESCSELECT * FROM EHR e ORDER BY e/ehr_id/value ASC, e/ehr_status/state DESC
LIMIT clause
The LIMIT clause specifies the maximum number of results to be returned.
Query syntax
LIMIT <number> OFFSET <number>
Examples
SELECT * FROM EHR e LIMIT 10SELECT * FROM EHR e LIMIT 10 OFFSET 20
Parameters
It is possible to have parameterized values in your query, making the query dynamic and reusable.
Query Syntax
SELECT <parameter>WHERE o/name/value = <parameter>WHERE o/data[<parameter>]/events[<parameter> and name/value = <parameter>] = <parameter>
More examples
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 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'}))
References
For more information on what AQL has to offer, read this page explaining AQL in more detail.