Академический Документы
Профессиональный Документы
Культура Документы
This document explains important concepts that are needed to understand the query results when
mixing SQL and Calculation View functionality. If you are unsure about certain terms that appear in
this document have a look at Section "Important Concepts" to check whether you can find more
details there.
This Note will provide a decision tree to understand what kind of combinations of SQL and
Calculation View logic should be avoided, discuss important concepts, highlight specific scenarios
that can lead to unexpected results and give specific recommendations for these scenarios. At the
end of the document further references are listed.
In a nutshell, Calculation Views make use of the Calculation Engine. The Calculation Engine was
developed for optimal performance and to support multi-dimensional reporting. It thus uses a
plethora of optimization options and modeling features. These optimizations and features can lead
to a non-relational behavior, i.e., a behavior that differs from what you would expect by simply
2
looking at a SQL statement that is used on the Calculation View without understanding the details of
the Calculation View model.
Like SQL queries over relational views, SQL queries over Calculation Views can be thought of as
executed in two steps: the Calculation View is evaluated and then the SQL query is evaluated on the
result. However, unlike a query on a SQL view, the evaluation of a Calculation View can depend on
the surrounding SQL query.
The result of evaluating a Calculation View may differ depending on the columns in the SELECT list or
in WHERE clauses, for example by changing the aggregation granularity. If this change in granularity
is lost in later SQL queries (e.g. stacked SQL queries) the processing granularity of the Calculation
View and of the final SQL will differ.
As will be explained below some calculations keep track of the granularity at which they are
calculated. Therefore, having calculations that keep track of granularity in both, SQL and Calculation
Views, can return unexpected, non-relational, results.
This non-relational behavior can be dealt with during the Front-End access, e.g., using the sap-
internal MDS interface or the open standard MDX to guard against unexpected behaviors. When
using SQL directly on the Calculation Views additional effort is needed to ensure that no surprising
results occur.
As a general guideline placing complex logic of one query into both, SQL and Calculation Views,
should be avoided, if possible. Instead calculation logic other than simple projections and
aggregations should either be placed exclusively in Calculation Views or performed in SQL.
Decision Tree
The decision tree is intended to give you guidance on where to put your calculation logic. The
decision tree can be found in the attachment. The following sections explain the individual steps in
the decision tree.
Reporting Interface
The first question is about your reporting interface. Are you querying the Calculation Views using SQL
or are you using MDS, MDX or TREXviaDBSL to query data? For example, SAP Analytics Cloud uses
MDS, while BW uses TREXviaDBSL when running HANA optimized queries.
a) move all granularity-tracking1 calculations to top-nodes, i.e., the uppermost nodes of the
Calculation Views that you are referring to in your query. Granularity-tracking calculations
can be, for example, count (*), User defined functions, currency conversion, or calculations
like the division of attributes. If you intend a calculation before aggregation or want to
calculate granularity-tracking measures at different aggregation granularities you have to
define calculations also at lower nodes. In this case additional care and testing is needed to
ensure consistent behavior.
b) define counters on higher nodes than calculated columns on which they are based
1
For an explanation of what is meant with the term "granularity-tracking" please see section "Concept
granularity-tracking calculations".
3
SQL interface
Granularity-tracking calculations
If granularity-tracking calculations are needed in a Calculation View all kind of complex calculations in
SQL should be avoided and queries should be kept as simple as possible. This means all kind of
expressions, calculations, and SQL functions in the aggregation or grouping statements should be
avoided and modeled in the Calculation View. Furthermore, any join and subquery logic in queries
should be moved and directly expressed in the Calculation View to control the granularity at which
the calculation of granularity-tracking calculations happen.
Alternatively, remove all granularity-tracking calculations from the Calculation Views and express
them inside the SQL query.
If both options (moving all logic into the Calculation View or into SQL) are not viable for you ensure in
addition to a) an b) of the previous section that
c) only the same aggregation is used within a stacked scenario"2. Different aggregation would,
for example, be if an included Calculation View used aggregation type SUM on a measure
while the including Calculation View used aggregation type MAX for the same measure (see
Section "Same aggregations within stacked scenarios" for details).
d) granularity-tracking aggregations like "VAR", "AVG"3 are not stacked. Stacking aggregations
"SUM", "MAX", and "MIN" is fine but do not mix them, e.g., do not combine "SUM" and
"MAX" (see Section "Granularity-tracking aggregations" for an example why this is
important).
and follow the additional steps in the decision tree to decide how to proceed.
If granularity-tracking calculations are not required you can mix logic in SQL and Calculation Views.
Push-Down
Next check if push-down of the SQL calculations is possible. In this context push-down means that
SQL logic (e.g., aggregating, joining, filtering, calculating expressions) is translated into basic
operations on tables while processing the Calculation View instead of being applied on top after the
Calculation View logic has been processed.
2
See section "Same aggregations within stacked scenarios" for an example of problems that otherwise might
occur
3
See section "Granularity-tracking aggregations" for an example and potential problems with it.
4
Therefore, if the push-down succeeds for all calculations no further calculations need to happen
during query runtime on top of the Calculation View because the Calculation View itself handles all
logic either directly or via push-down.
The crucial aspect here for understanding the impact of the non-relational behavior of Calculation
Views is that the SQL calculations that cannot be pushed-down need additional processing on top of
the Calculation Views. When additional processing occurs on top of Calculation Views this processing
does not take into account the non-relational behavior of Calculation Views. As a consequence, the
granularity at which granularity-tracking calculations in Calculation Views happen is affected from the
outside by the SQL request without taking the specific needs of granularity-tracking calculations into
account. This situation can occur when both of the following conditions hold:
This is why it is so important to keep granularity-tracking calculations at one place, in the Calculation
View or the SQL statement, if not all calculations can be pushed down. Otherwise the calculation of
granularity-tracking measures might happen at different levels of granularity and not fit together.
If instead all SQL calculations, JOINs, UNIONs, etc. can be pushed down the processing of the
Calculation View will take care that the non-relational behavior is respected.
The next sections will explain how you can check whether push-down is possible. Reasons why push-
down is sometimes not possible can be SQL functions for which no mapping between the SQL
function and Column store function is defined, or SQL functions for which simply no corresponding
implementation exists. Example of a functions that cannot be pushed down would be CASE. Other
reasons for additional processing on top of the Calculation View would be JOINs or UNIONs that are
defined in SQL.
How to check whether push-down is possible for the whole SQL statement
A good way to check globally for a SQL statement whether all calculations can be pushed-down is to
request an "explain plan" for the query (see e.g., SAP Note 2000002 for more information on explain
plan). To reduce the complexity of the analysis add the following SQL hint to your SQL query: "with
hint (NO_CALC_VIEW_UNFOLDING)". In general we do not recommend to block unfolding for
queries. However, in this specific context of checking push-down it can speed-up the analysis of a
query. More details about hint usage can be found, for example, in SAP Note 2142945.
When push-down is fully possible you will see the operator "COLUMN SEARCH" on top of the
operator "AGGREGATION":
Successful push-down
A first indicator that not all logic could be pushed down is if the explain plan contains stacked
"COLUMN SEARCH" operators. If you see such explain plans identify where "COLUMN SEARCHE"s are
defined on a Calculation View (3. line in screenshot below). If additional operations exist on top of
5
this "COLUMN SEARCH" you have a clear indication that push-down was not successful for all
calculations. In the example below the additional operation would be "TO_NVARCHAR" which was
not possible to push-down with earlier HANA releases.
In this example the "COLUMN SEARCH" for the Calculation View is not following an "AGGREGATION"
step (compare to screenshot where push-down was successful) which endangers the correct
handling of the granularity-tracking calculations inside the Calculation View. The columns that are fed
into the top-most "COLUMN SEARCH" depend on the additional calculations on top of the Calculation
View. In the example above the "TO_NVARCHAR" calculation requests the column "country_sid" to
be projected outside of the Calculation View processing.
This means the column "country_sid" has to be included in the granularity that is used inside the
Calculation View because of a reason that lies outside of the Calculation View, i.e., to be able to pass
it to the processing on top. As a consequence, the level of granularity is enforced from outside on the
Calculation View processing. Thus, depending on the SQL processing on top the behavior of the
Calculation View is affected. As is explained below in section "Concept granularity-tracking
calculations" varying granularities can change the result of granularity-tracking calculations.
The example above was used to illustrate the analysis of push-down and would in itself not lead to
unexpected results. However, you can imagine a situation where an additional SQL statement on top
removes the field "country_sid" from the GROUP BY. Someone looking at this SQL statement on top
only would be surprised why the calculation inside the Calculation View takes place at a granularity
where "country_sid" is still in the aggregation. Mixing now these Calculation View calculations with
calculations in this top query leads to a mixture of calculations with different granularities.
Such examples are not restricted to additional SQL statements on top of SQL statements. Section
"Filtering on attributes not requested in query " describes a situation where a blocked push-down
leads to unexpected results when a filter is applied on an attribute that is not contained in the
GROUP-BY of the SQL query. In this scenario the filter enforces a column in the Calculation View that
is not contained in the GROUP-BY of the SQL.
These examples should have illustrated that special care is always needed if push-down is not
possible for all calculations that are defined in SQL because this will lead to additional processing on
top of the Calculation View and thus can change the granularity of processing in the Calculation View
where granularity-tracking calculations are performed.
In short: query plans containing stacked "COLUMN SEARCH"s may easily change the list of requested
columns of the Calculation View and by this influence calculations with granularity-tracking
semantics of the Calculation View. For example, columns which are needed by the processing of
expressions, filters, JOINs, UNIONs, or aggregations on top of a Calculation View can influence the
granularity of counters in the Calculation View. When these requested columns are removed in later
SQL statements unexpected granularities might be used when processing granularity-tracking
calculations.
6
The next section will explain how individual SQL functions can be identified that can be one reason
for blocking push-down of the whole SQL statement.
If a SQL function is not included in the procedure result list (e.g. "strtobin") push-down will not be
possible. This could explain why using the explain plan shows that full push-down is not possible.
Other reasons could be UNIONs or JOINs that are defined in SQL.
If your analysis using explain plan or checking individual SQL functions shows that not all calculations
can be pushed down follow section "General heuristic in SQL scenario" and avoid defining
granularity-tracking calculations in SQL and in Calculation Views within the same query.
If your evaluation with explain plan shows that all calculations can be pushed-down check if Analytic
Privileges are used next.
Analytic Privileges
If Analytic Privileges are defined on other views than the lowest views in a stacked scenario follow
section "General heuristic in SQL scenario" and avoid distributing granularity-tracking calculations
into SQL and Calculation Views within the same query.
If no analytic privileges are used or only on the lowest views check next whether hints are necessary.
Hints
Even if all calculations can be pushed down and analytic privileges are only defined on the lowest
views still do not mix the locations where you place granularity-tracking logic if hints are required.
If also hints are not required, you can mix logic in SQL and Calculation Views.
Important Concepts
Instantiation
Instantiation is a process during which the defined Calculation View is simplified into a model that
fulfills the requirement of the query. This simplified model might for example, contain fewer columns
than the original model. In most simple terms a Calculation View that has field1 and field2 will be
pruned into a model that only consists of field1 if no other fields are requested by the query. This
instantiation happens at runtime, i.e., when executing a query. Other optimizations that can happen
are, for example, the pruning of joins (see e.g., https://blogs.sap.com/2017/10/27/join-cardinality-
setting-in-calculation-views/ for more details on join pruning). These changes in the instantiated
model can impact granularity-tracking calculations (e.g., amount1/amount2). As an example, imagine
the following data:
7
Germany Walldorf 10 5
Germany Rot 5 10
a) If only "Field1" is requested at the level where the calculation of "amount1"/"amount2" will
happen fields "amount1" and "amount2" will be aggregated first (we assume standard aggregation of
SUM):
Germany 15 15
Field1 amount1/amount2
Germany 1
b) If during intermediate processing "Field1" and "Field2" are requested the aggregation will happen
at a more fine granular level and look like:
Germany Walldorf 10 5
Germany Rot 5 10
Germany Walldorf 2
If you now look at the results after a final aggregation keeping only "Field1" the first example a)
without a different aggregation level in-between results in
Field1 SUM(amount1/amount2)
Germany 1
The second example b) with a different aggregation level in-between will result in
8
Field1 SUM(amount1/amount2)
Germany 2.5
Thus pruning (or adding4) columns during intermediate processing will lead to different results. It is
important to understand that this is not an erroneous processing. It is the result that comes out
when following the definition of the Calculation View in combination with its instantiation process
that can prune/add additional columns during processing based on the query request. This means
factors outside of the Calculation View change the granularity of processing inside the Calculation
View. As a consequence, different results of granularity-tracking measures can occur for reasons that
lie outside of the Calculation View.
This is now only a very simple example as an illustration of the principles. In real scenarios the effects
will be much more complex.
It is important to keep in mind that all fields that are needed for a certain calculation have to be kept
until the level at which they are needed: Imagine a source node that feeds into two nodes via
projections. If one projection only requests field "a" and the other projection requests field "b" the
granularity at the source node will involve both, "a" and "b" for both projections. This is illustrated in
the following screenshot:
In the screenshot Node A requests only field "a", while Node B only requests field "b". This means
the calculation "cc2" in Node A will be done at the granularity of field "a" only. Similarly, in Node B,
the calculation of "cc3" will be done with the granularity of field "b" only. As Node S feeds into Node
A and Node B and thus has to provide fields "a" and "b", calculation of "cc1" in Node S will happen
with granularity "a" and "b".
The instantiation process is discussed in more details in SAP Note 1764658 HANA Calculation Engine
Instantiation Process. A more extensive example of granularity-tracking calculations is discussed
4
"adding" in this context means more columns compared to the granularity of the final SQL query, while
"pruning" takes all columns of the Calculation View as the reference. As an illustrative example for adding of a
column, you might think of a filter on a column that is not in the final GROUP BY. Even though the column is not
needed in the final SQL, the filter will be added to the instantiated model so that the filter values can be
checked.
9
Example:
The following is a small example in which the granularity at which the calculations happened in the
past do not (a)) or do (b)) influence the result.
Example data:
1 3 2 3
1 2 3 4
2 4 1 3
I. Calculate first at granularity Week and Day, followed by an aggregation with granularity
Week
1 3 2 3 5
1 2 3 4 7
2 4 1 3 4
Week +
1 12
2 4
10
1 5 7 12
2 1 3 4
As you can see by comparing the results of I. and II., it does not matter, whether the calculation
happens at granularity Week and Day first before aggregating to granularity Week or doing the
calculation directly on the granularity Week. In contrast in b) different values will be obtained
I. Calculate first at granularity Week and Day, followed by an aggregation with granularity
Week5
1 3 2 3 6
1 2 3 4 12
2 4 1 3 3
Week *
1 18
2 3
5
In a pure relational model this would correspond to the following SQL query:
select
week,
sum(value1),
sum(value2),
sum("*")
from
(
select
week,
day,
value1,
value2,
value1*value2 "*"
from
<Table>
)
group by
week
11
1 5 7 35
2 1 3 3
This time, different results are received by I. and II. Results do differ when the calculations had
happened at granularity Week and Day prior to aggregating to granularity Week, or when
calculations happen directly on the granularity Week.
As explained above, the instantiation process can lead to differing aggregation granularities that
depend on "outside" factors, i.e., the SQL query. In the context of granularity-tracking calculations
this can therefore lead to surprising results.
The following examples will demonstrate that mixing aggregations within one stack can lead to
different results that depend on the granularity at which they had been originally calculated. In
section "Instantiation" it was discussed that the granularity after the instantiation process is affected
by the SQL queries that are directed to the Calculation View. Taken together this can lead to the
situation that changing the outside SQL query can change the resulting values due to the granularity-
dependency of the aggregations. A similar effect to the one discussed in the context of granularity-
tracking calculations can thus also occur for aggregations that are mixed.
The following example reuses the data from the previous section and calculates a SUM aggregation
followed by a MAX aggregation on granularity Week. After that a change to the outside SQL query
will be done by adding a filter that does not filter out any values (the filter is used only for illustrative
purposes - the same principle would hold for functions that cannot be pushed-down but request
columns, or JOINs, or UNIONs that implicitly request columns). Still, adding a not-effective filter
changes the granularity of the aggregation. In the context of mixed aggregations this will lead to
6
The corresponding SQL query would be:
select
week,
value1,
value2,
value1*value2 "*"
from
(
select
week,
sum(value1) value1,
sum(value2) value2
from
<Table>
group by
week
)
12
different values. Finally, the same change (adding of a filter) will be applied to an example where no
mixing of aggregations occurs. This will lead to the same results independent of the added filter.
a) Example of mixed aggregations leading to differing values when the intermediate granularity
changes.
SELECT
Week
MAX(value2)
FROM
<stacked Calculation View>
GROUP BY
Week
Assuming that only Week is requested by the SQL statement, the SUM aggregation
occurs on the granularity of Week at some intermediate aggregation of the Calculation
View:
Week SUM(value2)
1 7
2 3
Week MAX(value2)
1 7
2 3
Let's imagine a filter on Day that filters out values of a non-existing day and therefore should
not change the query results at all, is added.
SELECT
Week
MAX(value2)
13
FROM
<stacked Calculation View>
WHERE
Day!=<not existing>
GROUP BY
Week
However, contrary to best practices, the transparent filter flag (the transparent filter flag is e.g.,
described in the modelling guide) is not used. As the transparent filter is not used Day will be
implicitly kept in the aggregation granularity. This means the first intermediated aggregation SUM
would look like:
Even though the SQL statement only explicitly requests Week the additional Day filter
implicitly (marked in grey) enforces Day to be kept in the intermediate aggregation.
1 3 3
1 2 4
2 4 3
1 3 3
1 2 4
2 4 3
When aggregating now with granularity Week, as requested by the SQL statement, will lead
to
Week MAX
1 4
2 3
This means, changing the granularity of intermediate processing can affect the result when different
aggregations are stacked.
14
b) Example of same aggregations within the Calculation View stack. Differing intermediate
granularities have no impact
Week MAX(value2)
1 4
2 3
Week MAX(value2)
1 4
2 3
1 3 3
1 2 4
2 4 3
1 3 3
1 2 4
2 4 3
When aggregating on SQL level, removing Day, the same results will be obtained as without the
filter Day:
1 7 4
2 3 3
15
For illustrative purposes a filter example has been used but similar effects can be observed when
additional columns are added by SQL joins. Therefore, do not mix aggregations when placing logic
other than pure projections into your SQL.
Granularity-tracking aggregations
In the previous section aggregation MAX could be stacked also in complex scenarios, in which
intermediate granularities might change based on the outer SQL query. The same holds true for MIN
or SUM aggregations. However, other aggregations are often granularity-tracking and thus should
not be stacked. Again, let's have a look at an example.
In the following example stacking of aggregation VAR is done which will lead to probably unintended
results that differ depending on the granularity at which they are intermediately calculated. In
contrast, stacked MAX aggregations are shown which do not depend on the intermediate granularity
and thus do not lead to different results.
A B 10
A C 20
Compare the result of calculating VAR first on granularity Field1 and Field2, followed by calculating
VAR only on granularity Field1.
A B 0
A C 0
Field1 VAR(Measure)
A 0
Now compare to the result if VAR is directly calculated with granularity of Field1:
Field1 VAR(Measure)
A (10-15)^2+(20-15)^2
16
Therefore, intermediate granularities can influence the outcome of VAR aggregations. Thus VAR (or
similar aggregations like AVG etc.) should not be stacked. With aggregation MAX, MIN, or SUM the
values would not change depending on the intermediate aggregation granularity.
The example from above but with MAX as aggregation will thus lead to the same results:
A B 10
A C 20
Field1 MAX(Measure)
A 20
Field1 MAX(Measure)
A 20
In contrast to VAR, intermediate processing of MAX does not lead to different results and thus
stacked MAX aggregations are not prone to changes in intermediate granularity.
Non-relational
Non-relational is used as a term to differentiate the behavior of Calculation Views due to the
instantiation process from a pure SQL behavior where column pruning and similar concepts do not
play a role. Due to the optimization during instantiation Calculation Views can differ from a relational
database behavior. You can read "relational" as a shortcut for: behavior of SQL.
The following example will demonstrate the difference between querying a SQL View and querying a
Calculation View. To this end, the same query is run on a SQL View and a Calculation View that at first
sight both seem to represent the same model.
field1 field2 m1 m2
17
G BW 10 5
G NRW 6 3
If you want to create the table yourself you can use the following statement:
SELECT
FIELD1,
FIELD2,
sum(m1) "M1",
sum(m2) "M2"
FROM
dat
GROUP BY
FIELD1,
FIELD2;
SELECT
FIELD1,
sum("M1"/"M2")
FROM
18
sqlview
GROUP BY
FIELD1
SELECT
FIELD1,
sum("M1"/"M2")
FROM
"CVView"
GROUP BY
FIELD1
Which will lead to the calculation of sum( 6/3,10/5) = 4 which was the result of the query
When running the same query on the Calculation View the Calculation View integrates the
information that only "FIELD1" is requested and removes "FIELD2" from the aggregation. Thus the
Calculation View will return the following data:
19
The previous query on the sqlview will thus return "2" when applied to the Calculation View because
16/8=2
Unexpected results
"Unexpected results" are frequently also referred to as "surprising results". What is meant by this
expressions is that the results are correct given the Calculation View instantiation logic but
"surprising" or "unexpected" if a relational behavior is expected. The typical reason for unexpected
results is that logic is defined in SQL and cannot fully be pushed down (e.g., certain SQL functions), or
additional SQL JOINs, or UNIONs , or filters are defined that request implicitly additional columns
from the Calculation View.
In all of these cases, some logic outside of the Calculation View determines via implicit field requests
the granularity at which calculations in Calculation Views happen. In combination with granularity-
tracking calculations this can lead to results that differ from results in a pure relational setting (see
also previous section "Non-relational").
To illustrate implicitly requested columns, in the following examples the implicitly requested column
F2 is set in italic
JOIN-example
SELECT
F1
FROM
T1 JOIN T2 on
T1.F2=T2.F2
Filter example
SELECT
F1
FROM
T1
WHERE
F2='a'
Sub-SELECT
20
SELECT
F1
FROM
(
SELECT
F1,
F2
FROM
T1
GROUP BY
F1,
F2
)
GROUP BY
F1
Top-node
Often it is suggested to move calculations to the top node. This means that the calculation should be
defined in the Semantics node of the Calculation View that is exposed to the reporting statement.
E.g., if your SQL statement looks like "SELECT f1, f2, … fn from CV1, CV2…" make sure that
granularity-tracking calculations in CV1 and CV2 and of all Calculation Views included in CV1 and CV2
are moved to the Semantics node of CV1 and CV2.
Push-down
In this context push-down often refers to the ability to push logic that is defined in SQL into lower
processing layers by the Calculation View. You can find more details in section "Push-Down" in the
context of Decision Tree.
Unfolding
Unfolding refers to the process during which the Calculation View scenario is unpacked and
translated into SQL during the runtime of the query. With current HANA releases unfolding is the
default behavior of Calculation Views. The reason for this default setting is that "translating"
Calculation View logic into SQL allows a better integration with the SQL queries on top of the
Calculation View. This translation introduces a common "language" for the query on top and the
Calculation View which in turn allows for better optimizations. By this, faster execution times can be
expected. Whether complete unfolding can occur depends on whether all calculations can be pushed
down. Blockers are calculations that cannot be translated directly to relational algebra, e.g.,
anonymization nodes, and mixing of authorization modes.
21
In the current context unfolding can introduce an additional relational behavior to Calculation Views
which can change the non-relational behavior of Calculation Views. Sometimes these changes are not
wanted for historical reasons (results could be different than without unfolding in the past).
Therefore, several switches exist to prevent unfolding to happen. In general switching off unfolding
should be avoided to benefit from current and future optimizations. The following Notes provide
more information on unfolding:
background information:
limits:
2441054 - High query compilation times and absence of plan cache entries for queries
against calculation views
When case functions or expressions are used in aggregation columns there is a danger that these
functions cannot be pushed-down. The relevant example expressions are highlighted in yellow
below. Whether or not push-down is possible will then depend on the exact used expression. You
can check whether push-down occurs using the explain plan as described above in section "How to
check whether push-down is possible".
SELECT "product_text",
sum(case when "country_text" = 'ab' then "sales" end) AS "sales"
FROM "_SYS_BIC"."TEST/TESTVIEW"
GROUP BY "product_text"
From the SQL perspective it is clear that these columns are only needed for the join and therefore
can be ignored when calculating the granularity-tracking measures. To ensure a consistent handling
in this case it must be ensured that either all calculations can be pushed-down (as is the case in the
example below) or the suggestions of section "General heuristic in SQL scenario" have to be followed.
Join example:
SELECT "country_sid","country_text",
sum(T2."sales") AS "sales"
FROM "_SYS_BIC"."TEST/TESTVIEW" T1
join "CETEST"."CETEST_SC_FACTS" T2 on "country_sid"="region"
GROUP BY "country_sid","country_text"
Subquery example:
SELECT "country_sid","country_text",
sum("sales") AS "sales"
FROM "_SYS_BIC"."TEST/TESTVIEW"
WHERE "country_sid" IN (SELECT "region" from "CETEST"."CETEST_SC_FACTS")
GROUP BY "country_sid","country_text"
Specific Scenarios
In the following you will find some specific scenarios in which unexpected results can appear when
no further precautions are taken. Often these unexpected results become apparent when comparing
execution of the queries with and without unfolding. This does not mean that one of the results is
more correct than the other as they reflect different models (relational/non-relational). However,
you might want to achieve the same results irrespective of unfolding. For each scenario we give a
recommendation how to avoid these unexpected results and refer in most of the scenarios to a SAP
Note that contains more details. The recommendations are specific to the respective issues but still
assume that in addition the general guidance is followed as detailed in the decision tree like, for
example, to move granularity-tracking calculations to the top nodes. A scenario applies to your
current situation when each of the listed pre-requisites is fulfilled unless it is explicitly noted that
e.g., c1 OR c2 must be fulfilled.
Implicit casts when comparing input parameters to columns (SAP Note 2503726)
c) an implicit cast of the string column to date is expected, e.g., value of string_column='1972-04-01 10:00:00.00'
Take home message: Do not rely on implicit casts when comparing input parameters to columns
23
Data type of filter value differs from column on which filter is used (SAP Note 2170436)
a) you filter with a different data type than the defined type of a column, e.g., filter for "2.1" on an integer
column "a"
explicitely cast the value to the expected data type, e.g., TO_INT(decimalFilterValue) = "a"
Take home message: Explicitly cast filter values to the intended data type
a) the result of a calculated column exceeds the value range of its operands, e.g., a/b for a=1 and b=2, both
INTEGER
Cast operands to types that contain the result in their value range. An implicit cast to DECFLOAT is
used by SQL when unfolding takes place. If you want to ensure same results with not unfolded
executions cast to DECFLOAT, e.g. DECFLOAT("a")/DECFLOAT("b")
b) additional processing is done in SQL (e.g., projection, join, union, subselect), e.g., SELECT
SUM("CountCustomer") FROM (SELECT "product_sid", "customer_sid", "CountCustomer" FROM ..)
c1) there is no specification which attributes should be kept at the level when count distinct
(or other granularity-tracking measure) are calculated, e.g., there is no explicit GROUP BY in
the SQL projection
OR
c2) there is an explicit GROUP BY but also additional calculated columns in SQL that cannot
be pushed down
move all logic into SQL, or into Calculation Views, do not include logic in SQL and Calculation
Views, e.g.,
- to put it into SQL: SELECT "customer_sid", count distinct "Customer" FROM … (no intermediate projection)
- to put it into Calculation Views: define the count distinct in the Calculation View and do a direct SELECT on it without an intermediate SQL
Projection: SELECT "customer_sid", "countedCustomers" FROM …
Take home message: Do not distribute logic between SQL and Calculation Views
Using more than 1 Calculation View in a SQL query together with granularity-tracking measures (SAP
Note 1958063)
24
a) you want do use more than 1 Calculation View in your SQL query. In addition you use granularity-
tracking measures, e.g., SELECT a/b,… FROM CV1, CV2
In general try to avoid these scenarios. Check whether all calculations can be pushed down. If not
all calculations can be pushed down either model all calculations in SQL or all calculations in
Calculation Views but do not put calculation logic in both. If all SQL calculations can be pushed down
make sure that no hints are used and analytic privileges are only defined at the lowest views. If all
prerequisites are fullfilled you can define calculations in SQL and Calculation Views.
a) You want to achieve calculation before aggregation, e.g., logically you want to achieve sum(amount/rate)
instead of sum(amount)/rate
we are only considering Calculation Views here as these are the objects to be used in new
modeling projects (e.g., https://blogs.sap.com/2017/09/01/overview-of-migration-of-sap-hana-graphical-view-models-into-the-
new-xsa-development-environment/ ). Add a projection below the aggregation and define your calculations
there, e.g., calculate "amount"/"rate" in the projection node and aggregate in the top node
Take home message: Use additional Calculation View projections to achieve calculation before
aggregation. Thoroughly test whether you achieve the aggregation granularity that you expect.
Granularity-tracking measures and calculated columns based on attributes (e.g. : SAP Note 2088371)
Scenario 1
a) You define a calculated measure ("cc") that is based on an attribute ("a"), e.g., cc=a
make sure that the attribute used in the calculated column is requested in each query in which the
calculated column is not requested. Otherwise granularity-tracking measures might change
depending on whether the calculated column is requested in the query or not. This might be
unexpected because "cc" is defined as a measure and therefore is not expected to influence the
aggregation level. The reason for the potential difference in result is that requesting the calculated
measure adds the attribute on which the calculated measure is based to the aggregation granularity
when calculating granularity-tracking measures. As discussed in section "Granularity-tracking
calculationsConcept granularity-tracking calculations" changed granularities can lead to different
results of granularity-tracking measures.
One way to ensure that the attribute is always included in the aggregation is to use the "keep flag"
for the attribute on which the calculated column is based. Forcing an attribute to be included in the
aggregation might lead to a finer granularity and thus more processing of data. For details on the
usage of the keep flag see e.g., https://blogs.sap.com/2017/08/30/usage-of-keep-flag/
25
Take home message: Check usage of keep-flag when working with granularity-tracking calculations
Scenario 2
If calculated measures are based on attributes the calculation happens before the respective
attributes are aggregated. If the respective attributes are not requested by the query in the GROUP-
BY the granularity at which the granularity-tracking calculation happens can thus be surprising. In
contrast, if the calculated measure was based on measures alone e.g., measure1/measure2 the
calculation would not happen on each level of measure2 separately, instead the granularity would
only be influenced by the requested attributes.
Take home message: Try to avoid basing calculated measures on attributes or be aware of the
enforced granularity by the inclusion of the attribute in the calculation of the measure. To make
the aggregation granularity more explicit the attribute should always be requested by the query.
a) you want to only select one single calculated attribute from a Calculation View and no other fields
Take home message: Use keep-flag if you want to ensure records are returned when only
requesting a calculated column.
a) you want to filter on an attribute that is not requested in the query, e.g., SELECT value, SUM(measure) FROM
… WHERE filter='X' GROUP BY value
b) you have defined a granularity-tracking measure in the Calculation View, e.g., measure=amount1/amount2
c) you use a calculation in SQL that cannot be pushed down, e.g., "value"||'X'
per default the filter attribute will be added to the processing and thus influence granularity-
tracking measures (see concept "instantiation" above). Therefore, always add the attribute on which
the filter is based to the query, e.g., SELECT value, filter, SUM(measure) FROM … WHERE filter='X' GROUP BY value, filter
or use the transparent filter flag, described e.g., in the modelling guide
This scenario is focusing on the filter because here an easy remedy is available for this specific
situation. It is still recommended to follow the general guidance to not place logic into different
locations when non-commulative calculations and calculations that cannot be pushed-down are
involved. In the current scenario, the calculation that cannot be pushed-down should be placed
inside the Calculation View where also the granularity-tracking calculation is defined, or the
granularity-tracking calculation should be moved to SQL.
26
Take home message: Avoid filtering on attributes that are not requested in the query. Check usage
of transparent filter flag. If possible: follow the general guidance of not putting logic into different
locations when calculations are involved that cannot be pushed-down.
a) you want to calculate the number or records returned from a Calculation View, e.g., SELECT count(*) from
…
Either include a counter column that is set to "1" and sum up this column or make sure that the
relevant columns that should be used in the aggregation when calculating the counter are kept, e.g.,
use the keep flag (https://blogs.sap.com/2017/08/30/usage-of-keep-flag/).
Alternatively, do not use intermediate projections, or calculations in SQL when not all calculations
can be pushed down. Read SAP Note 1791464 to understand that the result of count(*) can change
when the set of requested fields changes between different queries with count(*).
Take home message: Handle count(*) with special care and clarify your expectations about the
result
Do not use virtual tables that are based on Calculation Views. Try to use cross-database access in a
multi-tenant environment (check attachment of SAP Note 2457320 to see if it becomes available for
Calculation Views in SAP Web IDE for SAP HANA)
Take home message: Virtual tables behave relational. Don't place them on remote Calculation
Views
Using a different aggregation type in query than defined in the Calculation View (SAP Note 2647957)
a) you use a different aggregation type in your query than modeled in your last node of the
Calculation View on which the query is based
See section "Same aggregations within stacked scenarios" for reasons why different
aggregation types should be avoided. SAP Note 2647957 explains the difference between old
repository and new HDI Calculation Views when the query aggregation type differs from the
modeled aggregation type in the Calculation View. The Note also provides an example how the
behavior can be switched.
SAP Note 2647957 explains the difference between old repository and new HDI Calculation Views
when filtering on measures in end user queries and how the intended behavior can be achieved.
27
Relevant Notes
For a general overview: