Overview
Some Junction resources expose list columns — columns whose value on each row is itself a list. For example, the Menstrual Cycle resource storesbasal_body_temperature as a list of {date, value} structs.
List columns cannot be selected directly as a Table Column. Instead, you aggregate their elements with a scalar-output subquery — a self-contained expression that unnests the list, optionally filters its elements, applies an aggregate function, and returns one scalar per outer row.
That scalar can be selected directly, or wrapped in a group-level aggregate (.mean(), .sum(), …) when used inside a GROUP BY.
Anatomy
A scalar-output subquery has three parts:SELECT agg(element) FROM UNNEST(list) WHERE <predicate>.
Aggregate a struct-field
Compute the mean basal body temperature per cycle, alongside the cycle’s period end and cycle end dates. Scalar columns can be selected directly next to subquery aggregates — they share the per-cycle output row.Aggregate a scalar-element list
When the list elements are scalars rather than structs (for example, a list of string tags or numeric samples), usecount with arg: null, or target the element explicitly with { "element": true } for any other aggregate.
Count the tags on each note row:
JSON DSL
JSON DSL
Choosing arg
Struct-field references work only on struct-element lists;
{ "element": true } works only on scalar-element lists.
Filter elements with WHERE
Thewhere predicate filters elements before the aggregate runs. The identifiers inside the predicate resolve against the unnested element:
- Struct-element lists: identifiers refer to struct fields of each element (e.g.,
"flow != 'none'"onmenstrual_flowreferences theflowfield of each struct). Unknown field names are rejected. - Scalar-element lists: the reserved identifier
elementrefers to the element value itself (e.g.,"element != 'unspecified'"). Any identifier other thanelementis rejected.
>, >=, <, <=, =, !=), logical (AND, OR, NOT), parentheses, and string/numeric literals.
Use inside GROUP BY
A scalar-output subquery in a grouped query must be wrapped in an outer aggregate. Period end, cycle end, and number of meaningful flow days, one row per period-start date:sum(inner_count)counts matching elements across the records.min(inner_min)andmax(inner_max)select the extrema across the records.mean(inner_mean)is an unweighted mean of the record-level means, not a pooled mean of all list elements.
sum and count, aggregate each with outer sum, and divide the resulting totals in your application. Avoid oldest or newest when records can share the same period-start index because ties are not defined.
Supported aggregates
Inside the subquery’sselect:
count— count of elements (or matching elements ifwhereis present).sum,mean,min,max,median,stddev— numeric aggregates over the element value or extracted struct field.
oldest and newest are not available inside a subquery — list elements have no inherent ordering.
Output column naming
The subquery’s inner aggregate function is added as a prefix, matching the standard aggregate-prefix convention.arg: null→$FUNC.$COLUMN(e.g.,count.menstrual_flow).- Struct field extract →
$FUNC.$COLUMN.$FIELD(e.g.,mean.basal_body_temperature.value). { "element": true }→$FUNC.$COLUMN.element(e.g.,sum.tags.element).
mean.mean.basal_body_temperature.value reads as “mean of per-cycle mean of basal_body_temperature.value”.