feat: support program-stage data element values in TE aggregate analytics [DHIS2-21763]#24387
Open
luciano-fiandesio wants to merge 3 commits into
Open
feat: support program-stage data element values in TE aggregate analytics [DHIS2-21763]#24387luciano-fiandesio wants to merge 3 commits into
luciano-fiandesio wants to merge 3 commits into
Conversation
…tics [DHIS2-21763]
Extend /api/analytics/trackedEntities/aggregate/{tet} so the value request
param can be a program-stage data element (event value), not only a tracked
entity attribute.
Event data-element values are multi-valued per tracked entity (one row per
event in analytics_te_event_<tet>), so a naive join fans out and makes GROUP BY
count events instead of tracked entities. Collapse each TE's events for the
stage to a single chosen row via row_number() and LEFT JOIN it back at TE
grain.
1db8994 to
e0ee63d
Compare
|
vietnguyenaa
approved these changes
Jul 8, 2026
vietnguyen
approved these changes
Jul 8, 2026
maikelarabori
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Extends the tracked-entity aggregate endpoint
/api/analytics/trackedEntities/aggregate/{trackedEntityType}so thevalueparameter can be a program-stage data element (an event value), not just a tracked-entity attribute.Previously
valueresolved only to a numeric tracked-entity attribute — a single column on the flat one-row-per-tracked-entity tableanalytics_te_<tet>. Event data element values live in a separate table (analytics_te_event_<tet>) with many rows per tracked entity (one per event), so they could not be aggregated. This PR reduces each tracked entity's events for the stage to one chosen event, joins it back, and aggregates it — giving correct per-tracked-entity results.valuenow acceptsprogramUid.programStageUid.dataElementUid(with an optional stage offset), in addition to the existing bare attribute UID.What this enables
aggregationType=COUNTover the data element counts non-null values (one per tracked entity), not events.[0]latest (default),[-1]the visit before,[1]the first.Example queries
The response is the same grid shape as the existing aggregate endpoint: one column per grouped dimension (carrying the dimension-item UID) plus a trailing numeric
valuecolumn; grouped org-unit UIDs resolve to names viametaData.items.Generated SQL
Aggregating a data element requires reducing each tracked entity's events for the stage to a single chosen event before joining, otherwise the join would match every event and the aggregation would count events instead of tracked entities.
row_number() over (partition by trackedentity order by occurreddate <dir>)+rn = <offset>selects one event per tracked entity (default: the latest event that carries the data element).jsonb_exists(eventdatavalues, '<de>')restricts to events that actually have the value (used instead of the?operator, whichNamedParameterJdbcTemplatewould misparse as a bind placeholder).status != 'SCHEDULE'excludes scheduled events (which have nooccurreddate), matching the row-level query.COUNTcounts non-null values.