> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction to measures

> How Atoti supports aggregated measures, store look-up measures, and user-defined measures, including measure chains, filters, logical-level aggregation, measure shifting, and null handling.

Measures are central to how Atoti aggregates and analyzes data.
They represent numerical computations based on data available to the cube.
A measure can range from simple aggregations like sums to more sophisticated user-defined logic.

## Which types of measures does Atoti support

Atoti supports several types of measures, each suited to different analytical needs:

### Aggregated measures

Aggregated measures are derived from numerical values in the original table.
Common aggregation functions include:

* SUM
* AVG
* MIN
* MAX

## Related reading

For a full list of available aggregate functions see

* [Atoti Java SDK](/engine/java-sdk/latest/cube/aggregation-functions)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.agg.html)

These functions operate over schema fields and are typically used to compute totals, averages, or other basic statistics.

### Store look-up measures

Store look-up measures provide contextual information that supports other calculations within the cube.
They are typically used to enrich analytical logic in user-defined measures (see below).

* Store look-up measures provide reference data such as conversion rates or classification label, without affecting the core aggregation logic
* The reference data is sourced from isolated tables in the database.
* These tables are not part of the main fact table but are linked through mappings or relationships.\
  For example, in a foreign exchange scenario, a look-up measure finds the exchange rate for the currency used in a financial transaction.

### User-defined measures

User-defined measures allow for custom calculations beyond basic aggregations. For example:

* Non-linear operations
* Conditional logic
* A combination of multiple aggregated measures
* A combination of aggregated measures, look-up measures and other user-defined measures

Each individual measure generates value based on the data in the cube.
The values are used by:

* Business users to analyze data using Atoti UI or other tools
* Other Atoti user-defined measures to create further measures in Atoti's cube

Consider a primitive measure such as `pnl.SUM` which is the sum of the pnl field.
This measure cannot aggregate correctly on the currency hierarchy.
This limitation is one reason why the currency hierarchy is often treated as a slicing hierarchy.

See the [hierarchies](./hierarchies) documentation page for more details.

To address this issue, the following pattern can be used:

* Create a measure called `pnl` and make it visible to users.
* When the query is filtered to USD, `pnl` delegates directly to `pnl.SUM`.
* When the query is filtered to another currency `XxX`, define additional measures:
  * A lookup measure that retrieves the forex rate between `XxX` and USD from the isolated forex store.
  * A conversion measure that multiplies `pnl.SUM` by this forex rate.

This approach ensures a consistent and correct aggregated result across all currencies.

## How does Atoti combine measures?

Measures are combined into a measure chain, where each measure builds upon the previous one.

<Frame caption="Data from tables is aggregated and combined to create complex measures in a measure chain.">
  <img src="https://mintcdn.com/activeviam/lTzImDUNm0cHRUws/images/atoti-concepts/measures-chain.png?fit=max&auto=format&n=lTzImDUNm0cHRUws&q=85&s=f22426a098ec5a298392952c7b840398" alt="Measures chain" width="777" height="1480" data-path="images/atoti-concepts/measures-chain.png" />
</Frame>

Atoti supports core mathematical operations for combining measures, such as:

* plus
* minus
* multiply
* divide

These operations can be applied across measures to form new ones, enabling flexible and reusable logic.

## Related reading

Find out how to create measures using:

* [Atoti Java SDK](/engine/java-sdk/latest/copper/copper_measures)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.measures.html#atoti.measures.Measures)

## How can measure calculation be refined with Atoti?

In Atoti, measures can be refined using filters and conditional logic, logical-level aggregation, and measure shifting.
These techniques allow users to tailor calculations to specific data subsets, hierarchy levels, or time periods.
This ensures that each measure reflects only the relevant data, helping users exclude outliers, compare time slices, and analyze specific members or groups within a hierarchy.
By refining how measures are calculated, users gain more accurate insights without modifying the underlying dataset.

### Filters and conditional logic

Measures in Atoti can include filters or conditional logic to control which data is used in calculations.
This ensures that each measure reflects only the relevant subset of data.

In other words, data from only specific hierarchy levels is used to calculate the value of the measure.
In this way, users can create focused, accurate calculations without needing to adjust the underlying dataset. This is useful for:

**Excluding data such as:**

* Outliers
* Test data
* Data received after the start of day
* Specific members that could cause double counting

**Including data such as:**

* Only selected members of a hierarchy
* Start-of-day data for comparison with intraday updates

**Comparing data such as:**

* Comparing a subset of members with the total across a hierarchy
* Comparing different time slices, like start-of-day versus current values

Find out how to apply filters to measures using:

* [Atoti Java SDK](/engine/java-sdk/latest/copper/copper_measures#measure-filtering)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.function.filter.html)

### Logical-level aggregation

Atoti supports logical-level aggregation. Measures can retrieve the value of other measures at a specific level of a hierarchy.
This is useful for:

* Grand totals: the sum of all the individual member values
* Parent values: the sum of all the individual members up to a given level
* Percentages or ratios

Find out how to apply conditional logic to measures using:

* [Atoti Java SDK](/engine/java-sdk/latest/copper/copper_measures#dynamic-aggregationleaf-operation)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.scope.html)

### Measure shifting

Measure shifting allows for comparisons across time periods or across different hierarchy members.
This is useful for:

* Day to day differences: the value from day -1 is shifted to day -2
* Comparing risk exposure across business units: credit risk exposure from counterparty A is shifted to counterparty B
* Comparing capital allocation by business unit: capital allocation from desk Y is shifted to desk Z

Shifting values along dates is also used for building a timeline of prices or values.

Find out how to shift measures using:

* [Atoti Java SDK](/engine/java-sdk/latest/copper/copper_measures#shift-measures)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.function.shift.html#atoti.shift)

## How does Atoti handle null values?

Atoti's aggregation functions have consistent null handling behavior:

* Null values are ignored in calculations
* If all input values are null, the result is empty

This default behavior is consistent across both the Java and Python SDKs, ensuring stable and reliable calculations even when working with incomplete datasets.

Developers can also implement their own logic within user-defined measures to treat nulls differently, such as substituting a default value.

Find out how to manage nulls using:

* [Atoti Java SDK](/engine/java-sdk/latest/datastore/datastore_config#default-values)
* [Atoti Python SDK](https://docs.activeviam.com/products/atoti/python-sdk/latest/api/atoti.Column.default_value.html)
