How measures run

A measure is one aggregation, such as sum("Sales"."Amount"), written once on a semantic model and used by every chart that shows it. The chart supplies the rows, the joins and the filters; the measure supplies the calculation, and this page explains the rules behind that split.

What runs when a chart shows a measure

Aggregates, windows and PARTITION BY ALL

Note

PARTITION BY ALL is a DataPrism macro, not part of the query language. Copying a measure's SQL into the SQL editor fails there.

Filters, QUALIFY and shares

Totals and KPI cards

Helper measures and references

Result types and NULLs

Patterns that return wrong numbers silently

These mistakes return a number without any error. Check them before you trust a result:

Questions, answered

Why is every rank 1 in my chart?

The window combines PARTITION BY ALL with a metric ORDER BY. The macro keeps every group-by column, so each partition holds exactly one row and every rank is 1. Write the ranked aggregate out instead, without the macro: rank() OVER (ORDER BY sum("Sales"."Amount") DESC).

Why is a total different from the sum of the rows above it?

A total is computed by running the query again at its own, coarser grain, with the summed-out group-by fields removed, not by adding the rows. Plain sum and count totals match the sum of the rows; ratios, averages and distinct counts do not. See Matrix visual.

Why does my filtered share percentage show the unfiltered share?

By design: windows see the data before your filters, so a share of total is computed against the unfiltered total. A filter on a group-by column is applied after the windows unless every involved window already partitions by that column.

Why does a dimension value come out arbitrary?

The dimension's key is not unique, so the join picked one of several matching rows for that fact row. Make the key unique, or read the value from a dimension whose key is unique.

Why can I not wrap a windowed measure in another window?

Windows run after aggregation, and a window inside another window is illegal. A windowed measure may be post-processed with scalar functions only, such as round("Revenue", 2). To change what the window computes, edit the window inside that measure.

Why does my KPI card show more than the same measure on a chart?

A card has no group-bys, so a windowed measure is collapsed onto a hidden timeline: numeric values are summed across the qualifying periods. A window shape that stays constant across the timeline is multiplied by the number of periods on a card. Filter the timeline columns on the card, or keep the measure additive, such as a lagInFrame shape. See KPI and Cards.

Why does my measure fail with an illegal aggregation error?

One aggregate sits inside another, directly or through a reference that inlines into it. Windows run after aggregation, so let the window wrap the aggregate: sum(sum("Sales"."Amount")) OVER (...). A comparison against a windowed value goes in an outer if() on the grouped row.

Which mistakes return wrong numbers with no error at all?

The wrong-pattern list on this page covers them all: a non-unique dimension key, an average of averages, counting over a fan-out, added distinct counts, a division without nullIf, an ambiguous bare column, PARTITION BY ALL without ORDER BY, a share read under a filter, a truncated unsorted result, totals read as sums, a period shift over missing periods, a snapshot summed across dates, and a literal date for a relative period.

Which result types can a measure return?

One of these: whole_number, decimal_number, date, date_time, time, duration, boolean or text. A result whose type is not one of them is refused when you save, and the message names the type.

How do I show the value at the latest period?

An aggregate cannot sit inside another aggregate, and windows run after aggregation, so the latest period cannot be picked inside the sum itself. Two patterns work:

Does referencing a measure compute it once?

No. A referenced name is substituted with its expression, so a helper used by two measures is computed as part of each of them, not once and shared. The chart declares the selected measures and everything they reference, sorted by name, so a helper appears in the query only when a shown measure reaches it.

Do I need to write the table name before a column?

Yes, qualify a column with its BI table name, such as "Sales"."Amount". A bare name keeps every joined table that has such a column, and as soon as two of them share it the reference becomes ambiguous (AMBIGUOUS_IDENTIFIER). Two things stay bare: the period columns in a window's ORDER BY and PARTITION BY, which name the chart's output columns, and a referenced measure, which is always written by its own name.