How Demantra Calculates and Stores Data

As an implementor, you should understand how Demantra calculates and stores data, because this can affect how you set up your solution. This chapter provides an overview of most important details.

This chapter covers the following topics:

How Data Is Stored

In order to understand how Demantra works, you should be aware of two central facts about how Demantra stores data:

These facts have wide-ranging implications. The following subsections expand these two facts, and the sections after that provide further details.

Data Is Stored at the Lowest Level

Demantra stores data only at the lowest possible item level, lowest possible location level, and base time unit. This has the following implications:

Data Is Stored Only Where the Sales Data Is Non-Null

Theoretically there might be a very large number of item-location combinations, but some items just might not be sold at some locations. It would be incorrect for Demantra to assume that all items could be sold at all locations during any time buckets. If Demantra assumed that, the result would be a very inaccurate forecast.

Instead, Demantra assumes (by default) that if there were no sales for a given combination during a specific time bucket, sales were not possible for that combination and time. Specifically, Demantra uses this assumption as follows:

In some cases, however, a null value for sales really does mean zero sales. Depending on the context, you can force Demantra to treat null values as zero values.

How Data Is Calculated at the Lowest Level

In general, the definition of a series also specifies how to calculate data at the lowest level, in the case when data changes at a higher level. Data can potentially change at a higher level either when it is imported at a higher level or when users edit a series while displaying data at a higher level.

Each series can be configured as proportional or non-proportional.

Other series are neither proportional nor non-proportional. Data for these series should not be changed except at the lowest level. For details, see “Summary of Calculation Options”.

How Data Is Calculated at Higher Levels

The definition of a series specifies how to calculate data at any level. A series can have either or both of the following expressions:

Server Expressions: Aggregation from Lower Levels

A server expression is an SQL expression that calculates the series data at any level by aggregating the associated lowest-level data. A very common server expression has the following form:

sum (table_name.update_column_name)

Here table_name.update_column_name is the table and column that stores data for this series.

If you view a combination at the lowest level, this expression reads the series value for one row in the given table. On the other hand, if you view a combination at a higher level, this expression sums the series values associated with all the rows that correspond to the child members.

Similarly, if you view a combination at a larger time bucket, this expression sums the series values associated with all the rows that correspond to the smallest time buckets for the combination.

A server expression can also aggregate by averaging or taking the minimum or maximum value of the child members.

Client Expressions: Calculations within a Level

A series can also have a client expression, which calculates data in a different way. In contrast to server expressions, a client expression always refers to data at the same level. You use client expressions to calculate numbers that cannot be calculated by aggregation from lowest-level data. For example, consider the following client expression for a hypothetical series called ErrorSquared:

(Expected - Actual)*(Expected - Actual)/(Expected*Expected)

For a given combination at a given time bucket, this expression calculates the ErrorSquared series directly in terms of the Expected and Actual series for the same combination at the same time bucket. As you can see from the following example, it would not be possible to compute this series by aggregating lowest-level members:

In addition to formulas as these, you can use client expressions to perform the following kinds of computations, which are not possible with server expressions:

Using Both Server and Client Expressions

A series can have both a server expression and a client expression. The client expression always takes precedence. Therefore, if a series has both expressions, the client expression is usually of the following form:

If (condition, client-expression-value, series-name)

Here series-name is a reference to the same series to which this client expression applies. This reference directs Demantra to the server expression that this series uses. Depending on whether the condition is true for a given cell, this expression returns either the client expression value or server expression value.

How Proportions Are Chosen

Demantra provides three general ways to specify the relative proportions of different combinations:

How Proportions Are Used

The following figure shows an upper-level member, ABCD, and its four child members. It also shows a reference series (Sales), and it shows the value of that series for each child member, all within the same time bucket.

the picture is described in the document text

Now suppose that series S is a proportional series that uses Sales as its reference series, and suppose that the value of S is changed to 350 for the parent member. In this case, the series S is split across the child members as follows:

the picture is described in the document text

How Splitting Handles Null Values

Now consider a case where the reference series has a null value for one of the child member. The proport mechanism ignores that member, as follows:

the picture is described in the document text

How Splitting Handles Zero Values

Now let us consider two cases where child members have zero values. In the first case, the reference series is zero for one of the child members, but has non zero numbers for other child members. Any member with 0 sales receives 0% of the split, as follows:

the picture is described in the document text

Notice that member A that has a null value for the reference series; for this member, the value of series S is null, rather than 0.

In the second case, none of the child members has a non zero value. In a case like this, the parent value is split equally among all members that have zero values for the reference series.

the picture is described in the document text

As always, if a child member has null for the reference series, the proport mechanism ignores that member entirely.

When and How Data Is Saved to the Database

A series may or may not be stored in the database. If it is stored, its data is saved in the series update field. Because you can potentially have different values from splitting at different levels, it is important to understand when and how Demantra saves data to the update field for a series.

For a series that has an update field, Demantra saves data to that update field as follows:

If the series also has a client expression, Demantra also saves data to that update field as follows:

Caution: Demantra does not automatically launch the database procedures. Instead, you must make sure to schedule the procedures to run periodically or otherwise automate running them. Use the Workflow Engine. See “Workflows”.