Background:
In a typical project, you may have business requirement to compute time period based calculations like below
- YTD - Year to Date (for Current Year and Previous Year)
- QTD - Quarter to Date (for Current Year and Previous Year)
- PTD - Period to Date (for Current Year and Previous Year)
- WTD - Week to Date (for Current Year and Previous Year)
- R4WK - Rolling 4 Weeks (for Current Year and Previous Year)
- R12WK - Rolling 12 Weeks (for Current Year and Previous Year)
- ....
Also these calculations may be based on normal time calendar (Gregorian) or Fiscal Calendar.
Problem Statement:
SAP HANA has multiple engines (OLAP engine, Join Engine and Calculation engine) to process data efficiently and OLAP engine is the fastest of all.
So to achieve the best performance, we have to make sure
a. Most of our computing happens in OLAP engine
b. No (or very minimal) data transfer between engines
So this translates to
1. Compute these period based calculation in the context of OLAP engine (i.e. Analytic View)
2. Model should be flexible to incorporate additional time period based KPIs (if required) in future.
Solution Option:
1. ZT_DATE_TRANSFORM table:
To achieve this we'll create a Time Period Transformation table (ZT_DATE_TRANSFORM), which will be joined to the FACT table in the data foundation layer of the Analytic View.
- DATE_SQL (Primary Key) - Date in DATE format : This will be used in report prompts (or joined to an Attribute View AT_TIME)
- FACT_DATE (Primary Key): Date in DATE format: (This will be used to join to the FACT table)
- TIME_KPI (Primary Key):
- CD (Current Day)
- WTD (Week to Date)
- PTD (Period to Date i.e. Month to Date)
- QTD (Quarter to Date),
- YTD (Year to Date),
- PW (Previous Week),
- R4WK (Rolling 4 Week),
- R12WK(Rolling 12 Weeks)
Note: there may be other KPIs defined like R13WK, R52WK etc.
- CYPY_FLAG: CY (for Current Year) and PY (for Previous Year)
The following table shows dataset for CD & WTD for both Current Year and Previous Year for 01-JAN-2014 & 02-JAN-2014
DATE_SQL | FACT_DATE | TIME_KPI | CYPY_FLAG |
---|---|---|---|
2014-01-01 | 2014-01-01 | CD | CY |
2014-01-01 | 2013-01-01 | CD | PY |
2014-01-01 | 2013-01-01 | WTD | CY |
2014-01-01 | 2013-12-31 | WTD | CY |
2014-01-01 | 2013-12-30 | WTD | CY |
2014-01-01 | 2013-12-29 | WTD | CY |
2014-01-01 | 2013-01-01 | WTD | PY |
2014-01-01 | 2012-12-31 | WTD | PY |
2014-01-01 | 2012-12-30 | WTD | PY |
2014-01-02 | 2014-01-02 | CD | CY |
2014-01-02 | 2014-01-02 | CD | PY |
2014-01-02 | 2014-01-02 | WTD | CY |
2014-01-02 | 2014-01-01 | WTD | CY |
2014-01-02 | 2013-12-31 | WTD | CY |
2014-01-02 | 2013-12-30 | WTD | CY |
2014-01-02 | 2013-12-29 | WTD | CY |
2014-01-02 | 2013-01-02 | WTD | PY |
2014-01-02 | 2013-01-01 | WTD | PY |
2014-01-02 | 2012-12-31 | WTD | PY |
2014-01-02 | 2012-12-30 | WTD | PY |
2014-01-03 | 2014-01-03 | CD | CY |
2014-01-03 | 2013-01-03 | CD | PY |
Data for PTD, QTD, YTD and other KPIs can be populated using similar logic.
01-JAN-14
YTD - one record i.e. 2014-01-01 for Current Year & one record i.e. 2013-01-01 for Previous Year
QTD - one record i.e. 2014-01-01 for Current Year & one record i.e. 2013-01-01 for Previous Year
PTD - one record i.e. 2014-01-01 for Current Year & one record i.e. 2013-01-01 for Previous Year
03-FEB-14
YTD - 34 records (from 2014-01-01 to 2014-02-03) for Current Year & 34 records (from 2013-01-01 to 2013-02-03) for previous Year
QTD - 34 records (from 2014-01-01 to 2014-02-03) for Current Year & 34 records (from 2013-01-01 to 2013-02-03) for previous Year
PTD - 3 records (from 2014-02-01 to 2014-02-03) for Current Year & 3 records (from 2013-01-01 to 2013-02-03) for previous Year
03-MAY-14
YTD - 123 records (from 2014-01-01 to 2014-05-03) for Current Year & 123 records (from 2013-01-01 to 2013-05-03) for previous Year
QTD - 33 records (from 2014-04-01 to 2014-05-03) for Current Year & 33 records (from 2013-04-01 to 2013-05-03) for previous Year
PTD - 3 records (from 2014-05-01 to 2014-05-03) for Current Year & 3 records (from 2013-05-01 to 2013-05-03) for previous Year
2. Data Foundation
As shown above, we are joining the Transaction Date (TXN_DT) from the FACT table (SALES) with the FACT_DATE field in the ZT_DATE_TRANSFORM table. The join type can be Referential and cardinality will be many-to-many (You can leave it blank from SP06 onwards).
Note: It is very essential you understand, why we are joining the FACT_DATE (not the DATE_SQL) to the TXN_DT field of the FACT table.
3. Logical Join:
Optional:
1. You may join your attributes view in the Logical join layer.
2. You may create additional calculated or restricted measure to compute AMT_CY (CYPY_FLAG = 'CY') and AMT_PY (CYPY_FLAG = 'PY')
4. Results:
Now the following Query will give you the required results
SELECT STORE, TIME_KPI, CYPY_FLAG, SUM(AMT)
FROM "_SYS_BIC"."abani.ytdsales/AN_SALES"
WHERE DATE_SQL = '2014-01-02'
GROUP BY STORE, TIME_KPI, CYPY_FLAG
Please note,
1. Since you are computing (Year to Date or Period to Date), You must pass a value for DATE_SQL in your Query.
2. The values in WTD or YTD an non-cumulative (i.e. You can't sum YTD of 01-Jan-14 to YTD of 02-Jan-14)
Alternately, you can use the following query (with TIME_KPI = 'CD' and CYPY_FLAG = 'CY'), where the model behaviour will be cumulative across dates.
SELECT STORE, DATE_SQL, SUM(AMT)
FROM "_SYS_BIC"."abani.ytdsales/AN_SALES"
WHERE TIME_KPI = 'CD' and CYPY_FLAG = 'CY'
GROUP BY STORE, DATE_SQL
Conclusion:
Using the above approach,
1. All the time period calculation happens in the context of the OLAP engine.
2. Adding other time period based KPIs as easy as populating the ZT_DATE_TRANSFORM table with additional records. No changes are required in the model.
3. Like any other Analytic View, this can be used in Calculation View for further business calculation (if any). Depending on your business requirement, please pay attention to setting appropriate filters (DATE_SQL = <something> or TIME_KPI = 'CD' & CYPY_FLAG = 'CY')