In this chapter, we will cover the following topics:
Setting up an Account or Measures dimension with a parent-child reference
Setting up dimensions with a generation reference
Adding columns for outline formulas
Adding the Solve Order column to tables that have ASO formulas
Adding and populating the Sort Order Column
Adding tables for varying attributes
Determining hierarchies in relational tables
Using the Essbase Outline Extractor to extract dimensions
Using Star Analytics to build your star schema from existing Essbase cubes
In this chapter, we will build components into our relational environment that will allow us to successfully build an Essbase database and facilitate drill-through reporting. Although we are discussing relational data sources, the properties, attributes, and concepts discussed in this chapter can be used to build hierarchies off data sources such as flat files for example. The techniques used here can be used in tools like Essbase Administrative Services, Essbase Integration Services, and Essbase Studio. This chapter also has recipes on the Essbase Outline Extractor and Star Analytics. These two tools allow us to extract hierarchies from existing Essbase cubes. We would use these tools to extract existing hierarchies or modify existing hierarchies to build all or parts of our star schema.
In this recipe, we will set up a relational table in a parent-child reference format. We will also review the type of properties that can go in each column and their definitions. The Account or Measure dimension is normally the most dynamic dimension in a financial database and it is recommended that you use the parent-child structure to build the dimension in a relational environment. The parent-child reference also allows ragged hierarchies without having to add columns to your tables when an additional level or generation is needed. We will also review an alternative method, which requires us to use the measures field in our fact table to build our Measure dimension.
To get started, open your SQL Server Management Studio, and add a database called TBC
. For this recipe, we are using T-SQL, but the PL\SQL equivalent will be provided where applicable. You should add a SCHEMA called TBC
using tools such as TOAD, SQL Developer, or Golden, if you are using Oracle.
Run the following scripts to create the
Measures
table. We can change the script below to PL/SQL by replacingint
with INTEGER andvarchar()
with VARCHAR2(). A screenshot of the table follows the script:--This is the syntax in T-SQL create table MEASURES ( SORTKEY int not null, MEASURESID int not null, PARENT varchar(85) null , CHILD varchar(85) not null, MEASURES_ALIAS varchar(85) null , CONSOLIDATION varchar(85) null , TWOPASSCALC varchar(85) null , STORAGE varchar(85) null , VARIANCEREPORTING varchar(85) null , TIMEBALANCE varchar(85) null , SKIP varchar(85) null , UDA varchar(85) null , FORMULA varchar(255) null , COMMENT_ESSBASE varchar(85) null , constraint PK_MEASURES primary key (MEASURESID) ) Go
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.
Execute the following scripts to add the data to your table:
INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING, TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (100,1,'Measures','Profit','','+','','X','','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING, TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (200,2,'Profit','Margin','','+','','X','','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (300,3,'Margin','Sales','','+','', '','','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (400,4,'Margin','COGS','Cost of Goods Sold','-','','','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (500,5,'Profit','Total Expenses','','-','','X','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (600,6,'Total Expenses','Marketing','','+', '','','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (700,7,'Total Expenses','Payroll','','+','','','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING, TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (800,8,'Total Expenses','Misc','Miscellaneous','+', '','','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (900,9,'Measures','Inventory','','~','','O','','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING, TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE) VALUES (1000,10,'Inventory','Opening Inventory','','+','','','E','F','','', 'IF(NOT @ISMBR(Jan)) "Opening Inventory"=@PRIOR("Ending Inventory");ENDIF;"Ending Inventory"="Opening Inventory"+Additions-Sales;',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1100,11,'Inventory','Additions','','~','','','E','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING, TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1200,12,'Inventory','Ending Inventory','','~','','','E','L','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1300,13,'Measures','Ratios','','~','','O','','','','','',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1400,14,'Ratios','Margin %','','+','T','X','','','','','Margin % Sales;',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1500,15,'Ratios','Profit %','','~','T','X','','','','','Profit % Sales;',''); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS, CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE, SKIP,UDA,FORMULA, COMMENT_ESSBASE) VALUES (1600,16,'Ratios','Profit per Ounce','','~','T','X','','','','', 'Profit/@ATTRIBUTEVAL(Ounces);','');
The MEASURES
table has the following columns:
COLUMN |
DESCRIPTION |
---|---|
This column is the integer that helps you sort the MEASURES in the order that you want them to appear in the hierarchy | |
This ID is used as the PRIMARY KEY in the MEASURES table and as a FOREIGN KEY in the fact table | |
This column is the Parent in the hierarchy | |
This column is the Child of the Parent column | |
This is a more intuitive description of Measures normally defined by the business | |
This field has the aggregation type for the Child column | |
This field has the value "T" if the aggregation requires a second pass through the outline for the results to be right | |
Storage can have many values and will determine how or if the data in the outline is stored or dynamically calculated | |
The Variance Reporting column is used to mark Expense accounts for reporting variances | |
The Time Balance column is used with your time dimension to determine whether to use LIFO, FIFO, or the Average method for a specific measure | |
The Skip column works with Time Balance to determine how to treat #MISSING or Zero values | |
The User Defined Attribute is useful for many purposes including outline formulas, calculation formulas, and the retrieval of data by the criteria defined by the business | |
These are the outline formulas used in the BSO model | |
These are simply comments on the meta-data stored in this table |
In step 2, we load the data. The following are descriptions of what goes into some of these columns as per Oracle's documentation.
These are the valid Consolidations values:
TYPE |
TYPE DESCRIPTION |
TYPE LONG DESCRIPTION |
---|---|---|
Percent |
Expresses as a percentage of the current total in a consolidation | |
Multiplication |
Multiplies by the current total in a consolidation | |
Addition |
Adds to the current total in a consolidation | |
Subtraction |
Subtracts from the current total in a consolidation | |
Division |
Divides by the current total in a consolidation | |
Never |
Excludes from all consolidations in all dimensions | |
Ignore |
Excludes from the consolidation |
This is the valid Two Pass value:
TYPE |
TYPE DESC |
TYPE LONG DESCRIPTION |
---|---|---|
Two Pass Calculation |
Requires a two-pass calculation (applies to accounts dimensions only) |
These are the valid Storage values:
TYPE |
TYPE DESC |
TYPE LONG DESCRIPTION |
---|---|---|
Never Share |
Never allows data sharing | |
Label Only |
Tags as label only (store no data) | |
Store Data |
Sets member as stored member (non-Dynamic Calc and not label only) | |
Dynamic Calc and Store |
Creates as Dynamic Calc and Store | |
Dynamic Calc |
Creates as Dynamic Calc |
This is the valid Variance Reporting value:
TYPE |
TYPE DESC |
TYPE LONG DESCRIPTION |
---|---|---|
Expense |
Treats as an expense item (applies to accounts dimensions only) |
These are the valid Time Balance values:
TYPE |
TYPE DESC |
TYPE LONG DESCRIPTION |
---|---|---|
Average |
Treats as an average time balance item (applies to accounts dimensions only) | |
First |
Treats as a first time balance item (applies to accounts dimensions only) | |
Last |
Treats as a last time balance item (applies to accounts dimensions only) |
These are the valid Skip options per Oracle's Documentation:
Using the parent-child reference table structure will depend on whether we know that our Measures and Accounts are going to change often. The structure of your fact table will have to change if you decide to use Measure tables. A fact table that has the Measures going down a table vertically, as rows, will allow us to use the Measures column in the fact table to join to the MEASURES table. The following screenshot illustrates how this design will look:

We can easily add accounts or change parent-child associations using this format without having to modify the fact table. On the other hand, if our fact table has Measures horizontally, in columns, then the Measures dimension will have to be built in Essbase Studio or Essbase Integration Services instead. The following screenshot is an example of what a fact table, with Measures as columns, would look like:

The Beverage Company (TBC) sample database's SALES and SALESFACT tables are examples of the two different formats.
You can find an example of the MEASURES dimension being built in the recipe Creating hierarchies using a Parent-child reference table in Chapter 3. For an example on how to build the MEASURES dimension using Essbase Studio from the fact table, refer to the recipe Building a Measures dimension from the fact table in Chapter 4.
In this recipe, we will build a table in a generation reference format. The SUPPLIER is a geographical dimension. Geographic dimensions are natural hierarchies, which means that the generations are related to each other naturally and there is normally a one-to-many relationship. A generation reference format is common in a relational environment as it can be used to conduct relational reporting as well. The same cannot be said about the parent-child structure.
To get started, open your SQL Server Management Studio, and add a TBC database. Add a SCHEMA using a tool such as TOAD, SQL Developer, or Golden, if you are using Oracle.
Run the following scripts to create the
SUPPLIER
table. We can change the script below to PL/SQL by replacingint
with INTEGER andvarchar()
with VARCHAR2(). Following the scripts is a screenshot of the table:--This is the syntax in T-SQL create table SUPPLIER ( SUPPLIERID int not null, SUPPLIER_ALIAS varchar(50) null , ADDRESS varchar(25) null , CITY varchar(25) null , STATE varchar(25) null , ZIP varchar(20) null , COUNTRY varchar(25) null , constraint PK_SUPPLIER primary key (SUPPLIERID) ) go
Execute the following scripts to add data to the
SUPPLIER
table:INSERT INTO SUPPLIER(SUPPLIERID,SUPPLIER_ALIAS,ADDRESS,CITY,STATE,ZIP,COUNTRY)VALUES (1,'High Tech Drinks','1344 CrossmanAve','Sunnyvale','California','94675','USA'); INSERT INTO SUPPLIER(SUPPLIERID,SUPPLIER_ALIAS,ADDRESS,CITY,STATE,ZIP,COUNTRY)VALUES (2,'East Coast Beverage','900 Long RidgeRd','Stamford','Connecticut','92001','USA'); INSERT INTO SUPPLIER(SUPPLIERID,SUPPLIER_ALIAS,ADDRESS,CITY,STATE,ZIP,COUNTRY)VALUES (3,'Cool Canadian','1250 Boul ReneLevesque','Montreal','New York','H3B-W4B','Canada');
Select from the
SUPPLIER
table to see the results:Select * From SUPPLIER;
In step 1, the SUPPLIER
table was created and in step 2 the data was populated. A generation in Essbase begins with generation 1 at dimension because the name of the cube in the outline is generation 0. We can tell from the structure of the table that it is clearly set up in generation reference as depicted in the following grid:
COLUMN |
DESCRIPTION |
---|---|
SUPPLIERID |
The PRIMARY KEY and a FOREIGN KEY |
COUNTRY |
Generation 2 |
STATE |
Generation 3 |
CITY |
Generation 4 |
ZIPCODE |
Generation 5 |
ADDRESS |
Generation 6 |
For more information on how to build the SUPPLIER dimension using Essbase Studio, refer to the recipe Creating hierarchies using a Generation reference table in Chapter 3.
In this recipe, we will add columns to our MEASURES
table, so that we can later add a formula to the dimension's members. The importance of this is apparent when you consider that the
Aggregate Storage (ASO) model does not use the same syntax as the Block Storage (BSO) model for their outline formulas. The ASO outline uses Multidimensional Expressions (MDX), which is the standard syntax convention for OLAP applications. We can use our table for both BSO and ASO applications by adding an additional column for the ASO model's formulas.
To get started, open SQL Server Management Studio, and add a database called TBC
. In this recipe, we are using T-SQL, but the PL-SQL equivalent for the examples has been included in the following code snippet. The MEASURES
dimension was created in the recipe Setting up an Account or Measure dimension with parent-child reference in Chapter 1. We need to complete step 1 of the aforementioned recipe before we continue.
Execute the following script to add a column to the
MEASURES
table. Following the script is the screenshot of the table after the modification:--This is the syntax in T-SQL Alter Table MEASURES Add FORMULA_MDX VARCHAR(4000) NULL; --This is the syntax in PL\SQL Alter Table MEASURES ADD FORMULA_MDX VARCHAR2(4000) NULL; --Delete content of the table to avoid issues with executing this execise Delete From MEASURES;
Execute the following script to add a row with the new formula:
--This is the syntax for both T-SQL and PL\SQL INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE, FORMULA_MDX) Values(0, 14, 'Ratios', 'Margin %', '', '+', 'T', 'X', '', '', '', '', 'Margin % Sales;', '', '[Measures].[Sales] / [Measures].[Margin];'); INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE, FORMULA_MDX) Values(0, 15, 'Ratios', 'Profit %', '', '~', 'T', 'X', '', '', '', '', 'Profit % Sales;', '', '[Measures].[Sales] / [Measures].[Profit];');
In step 1, the column FORMULA_MDX
is added to the MEASURES
table. The script in step 2 adds the new rows with the FORMULA_MDX
column included. The objective of this recipe is to show you that the syntax is different every time you use a table for both an ASO and BSO set of applications, so you need to have two formula columns. You can see how different the syntax is in the following code snippet, but if you need a more detailed explanation on this, please visit: http://www.oracle.com/technetwork/middleware/bi-foundation/4395-calc-to-mdx-wp-133362.pdf. This is Oracle's white paper on Converting Calc Formulas to MDX in an Essbase Outline.
In this recipe, we will include an additional column to our MEASURES
table to specify the solve order for the hierarchy. The ASO outline does not have the Two Pass Calc option in its Account dimension; as a result, you will have to specify the solve order by adding an additional column.
To get started, open SQL Server Management Studio, and add a database called TBC
. In this recipe, we are using T-SQL, but the PL\SQL equivalent is provided in the examples. The MEASURES
dimension was created in the recipe Setting up an Account or Measure dimension with parent-child reference in Chapter 1. We need to complete step 1 of the aforementioned recipe before we continue.
Execute the following script to add the
FORMULA_MDX
andSOLVE_ORDER
columns to theMEASURES
table, if it does not exist:--This is the script in T-SQL Alter Table MEASURES Add FORMULA_MDX VARCHAR(4000) NULL; Alter Table MEASURES Add SOLVE_ORDER INT NULL; --This is the script in PL-SQL Alter Table MEASURES ADD FORMULA_MDX VARCHAR2(4000) NULL; Alter Table MEASURES Add SOLVE_ORDER INTEGER NULL;
Execute the following scripts to add the formula and the solve order values to the
MEASURES
table:INSERT INTO MEASURES (SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOP ASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA,COMMENT_ESSBASE,FORMULA_MDX, SOLVE_ORDER) Values(0, 14, 'Ratios', 'Margin %', '', '+', 'T','X', '', '', '', '', 'Margin % Sales;', '', '[Measures].[Sales] / [Measures].[Margin];', 20); INSERT INTO MEASURES(SORTKEY,MEASURESID,PARENT,CHILD,MEASURES_ALIAS,CONSOLIDATION,TWOPASSCALC,STORAGE,VARIANCEREPORTING,TIMEBALANCE,SKIP,UDA,FORMULA, COMMENT_ESSBASE, FORMULA_MDX, SOLVE_ORDER) Values(0, 15, 'Ratios', 'Profit %', '', '~', 'T', 'X', '', '', '', '', 'Profit % Sales;', '', '[Measures].[Sales] / [Measures].[Profit];', 20);
Select from the table to see the values that you added:
We started this recipe by adding the SOLVE_ORDER
column to the MEASURES
table. We also added two new rows with the SOLVE_ORDER
populated. The objective of this recipe is to show you that the SOLVE_ORDER
value has to be higher than its respective components in order for the formula to return the correct values. We should consider the following steps when assigning SOLVE_ORDER
:
Set up in
SOLVE_ORDER
in increments of tens or twenties for clarity and consistency.When the default is not specified,
SOLVE_ORDER
is zero, but it is good practice to always specify theSOLVE_ORDER
to remove ambiguity and define the calculation's priority.
In previous releases of Essbase, a developer had the option of building a hierarchy in ascending or descending alphabetical order via a build rule. If you wanted to sort the hierarchies in a different order, then you would go into Essbase Administrative Services (EAS). Then, open the outline, and drag and drop the members in the order that the business wanted or extract the dimension using an Outline Extract utility, sort the hierarchy, and use a build rule to rebuild the dimension. In contrast, when we are using Essbase Studio, in version 11.1.2.1, we are going to have to define the Sort Order in the relational environment. If you have the Oracle's data-governance software Data Relationship Management (DRM), this task will be handled there, but this recipe shows you how to load the Sort Order field with some SQL knowledge and Excel.
To get started, open SQL Server Management Studio, and add a database called TBC
, if you have not already done it. In this recipe, we are using T-SQL and providing the PL\SQL equivalent where the syntax is different. You need to add a SCHEMA instead and use a tool like TOAD or Golden, if you are using Oracle. You should also open an Excel workbook.
Execute the following query to create the
YEARS
table. We can change the script below to PL/SQL by replacing int with INTEGER and varchar() with VARCHAR2():--For T-SQL user Create Table YEARS( YEARID int NOT NULL, YEAR int NULL, QUARTER varchar(80) NULL, MONTH varchar(80) NULL, MONTH_ALIAS varchar(80) NULL, Constraint PK_YEAR_YEARID Primary Key(YEARID Asc) );
Execute the following script to add the SORT_ORDER column:
--This is the syntax in T-SQL Alter Table YEARS Add SORT_ORDER INT NULL; --This is the syntax in PL/SQL Alter Table YEARS Add SORT_ORDER INTEGER NULL;
Open Excel and enter the
YEARS
dimension's data starting with field A1, as follows:Sort the hierarchy manually, if it does not look right in the order specified in the preceding screenshot. Enter the number
1
in cell F1 and formula=F1+1
in cell F2.Click on cell F2, then click on the box to the right and bottom of the cell, and drag it down to cell F12.
Enter the following concatenation string in cell G1, select G1, and press CTRL+C. Select range G2:G12, and press CTRL+V to paste the concatenation string:
="Insert Into TIME Values (" & A1 & ", " & B1 & ", '"& C1 & "', '" & D1 & "', '" & E1 & "', '" & F1 & "');"
Copy range G1:G12, open up SQL Management Studio, connect to the
TBC
database, paste the range in the query window, and execute the following queries:Insert Into YEARS Values(1, 2011, 'QTR1 11', 'Jan 2011', 'January 2011', '1'); Insert Into YEARS Values(2, 2011, 'QTR1 11', 'Feb 2011', 'February 2011', '2'); Insert Into YEARS Values(3, 2011, 'QTR1 11', 'Mar 2011', 'March 2011', '3'); Insert Into YEARS Values(4, 2011, 'QTR2 11', 'Apr 2011', 'April 2011', '4'); Insert Into YEARS Values(5, 2011, 'QTR2 11', 'May 2011', 'May 2011', '5'); Insert Into YEARS Values(6, 2011, 'QTR2 11', 'Jun 2011', 'June 2011', '6');Insert Into YEARS Values(7, 2011, 'QTR3 11', 'Jul 2011', 'July 2011', '7'); Insert Into YEARS Values(8, 2011, 'QTR3 11', 'Aug 2011', 'August 2011', '8'); Insert Into YEARS Values(9, 2011, 'QTR3 11', 'Sep 2011', 'September 2011', '9'); Insert Into YEARS Values(10, 2011, 'QTR4 11', 'Oct 2011', 'October 2011', '10'); Insert Into YEARS Values(11, 2011, 'QTR4 11', 'Nov 2011', 'November 2011', '11'); Insert Into YEARS Values(12, 2011, 'QTR4 11', 'Dec 2011', 'December 2011', '12');
The following are the steps in this recipe:
We added the
YEARS
table to theTBC
database.We added the
SORT_ORDER
column to theYEARS
table.We added an integer used to sort the members.
We also entered the
YEARS
dimension into an Excel sheet and sorted ourYEARS
hierarchy.After placing the
SORT_ORDER
into column F1, we pasted the correctSORT_ORDER
and concatenateInsert
statements together with the values in Excel.Finally, we used the
Insert
statements in the Excel workbook to update theYEARS
table using the SQL Management Studio.
The following is what your YEARS
hierarchy should look like without the SORT_ORDER
column:
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
|
Essbase Studio will enter February into the outline before January, May will be after June, August will be before July, and the fourth quarter will be completely out of order. For this reason, it is suggested that you add a SORT_ORDER
column to all of your dimension tables.
Refer to the Using Sort Order on data elements recipe in Chapter 2 to learn how to set the sort order for your metadata elements.
The varying attributes is an attribute dimension that maps to multiple dimensions. The concept of varying attributes in a relational environment is depicted by creating a mapping table. In this recipe, we will build a mapping table that joins the SALESMAN
table to the Product
and Market
tables. We will also see how this format works for a varying attribute.
To get started, open SQL Server Management Studio, and add a database called TBC
. In this recipe, we are using T-SQL, but the PL\SQL equivalent is provided in the examples.
Create and populate a
SALESMAN
table with following script. We can change the script below to PL/SQL by replacingint
with INTEGER andvarchar()
with VARCHAR2():--This is the syntax in T-SQL Create Table SALESMAN( SALESMANID int NOT NULL, SALESMANNAME varchar (80) NULL, Constraint PK_SALESMAN_SALESMANID Primary Key (SALESMANID) ); go --This scripts enter the data into the SALEMAN table Insert Into SALESMAN Values(1, 'John Smith'); Insert Into SALESMAN Values(2, 'Jose Garcia'); Insert Into SALESMAN Values(3, 'Johnny Blaze');
Create and populate a
PRODUCTS
table:--This is the syntax in T-SQL Create Table PRODUCTS( PRODUCTID int NOT NULL, SKU varchar(15) NULL, SKU_ALIAS varchar(25) NULL, Constraint PK_PRODUCTS_PRODUCTID Primary Key (PRODUCTID) ); --Insert data into PRODUCTS table Insert Into PRODUCTS Values(1, '100-10', 'Cola'); Insert Into PRODUCTS Values(2, '100-20', 'Diet Cola'); Insert Into PRODUCTS Values(3, '100-30', 'Caffeine Free Cola');
Create and populate a
MARKETS
table:--This is the syntax in T-SQL Create Table MARKETS( STATEID int NOT NULL, STATE varchar(25) NULL, Constraint PK_MARKETS_STATEID Primary Key (STATEID) ); --Insert data into MARKETS table Insert Into MARKETS Values(1, 'New York'); Insert Into MARKETS Values(2, 'Massachusetts'); Insert Into MARKETS Values(3, 'Florida');
Create and populate a
SALESMANMAP
table:--This is the syntax in T-SQL Create Table SALESMANMAP( SALESMANID int NOT NULL, STATEID int NOT NULL, PRODUCTID int NOT NULL, Constraint PK_SALESMANMAP Primary Key (STATEID, PRODUCTID) ); --Insert data into the SALESMANMAP table Insert Into SALESMANMAP Values(1,1,2); Insert Into SALESMANMAP Values(1,2,3); Insert Into SALESMANMAP Values(2,1,1); Insert Into SALESMANMAP Values(2,2,2); Insert Into SALESMANMAP Values(3,3,1); Insert Into SALESMANMAP Values(3,3,3);
Execute the following scripts to join the tables:
Alter Table SALESMANMAP Add Constraint FK_SALESMANMAP_PRODUCTID Foreign Key(PRODUCTID) References PRODUCTS (PRODUCTID); Alter Table SALESMANMAP Add Constraint FK_SALESMANMAP_SALESMANID Foreign Key(SALESMANID) References SALESMAN (SALESMANID); Alter Table SALESMANMAP Add Constraint FK_SALESMANMAP_STATEID Foreign Key(STATEID) References MARKETS (STATEID);
Execute the following query to see the relationship between the
Market
,Product
, andSalesman
:Select T4.SALESMANID, T2.SALESMANNAME, T4.STATEID, T3.STATE, T4.PRODUCTID, T1.SKU_ALIAS From PRODUCTS T1, SALESMAN T2, MARKETS T3, SALESMANMAP T4 Where T1.PRODUCTID = T4.PRODUCTID and T2.SALESMANID = T4.SALESMANID and T3.STATEID = T4.STATEID and T2.SALESMANNAME = 'John Smith'
The relationships between the tables created and populated in steps 1 through 4 are shown in the following diagram:

The SALESMANMAP table joins the other three tables of which SALESMAN is the varying attribute. Salesman varies depending on the state and product you want to report on. We can retrieve the relationship between tables using the query shown in step 5. The results for this query are displayed in the following screenshot:

The important thing to note about this varying attribute example is that it is possible for two Salesmen to conduct business in the same Market, but it is not possible for the same two Salesmen to sell the same Product in the same Market. This logic is maintained by the constraints placed on the SALESMANMAP mapping table.
In this recipe, we will determine hierarchies in relational models. This recipe will also go over some of the main attribute dimension types. Attribute dimensions are dynamic dimensions that allow users to report on their data without increasing the foot print of the database. Attributes work in a similar way to an alternate hierarchy, but unlike an alternate hierarchy you can use an attribute dimension to conduct cross tab reporting on a different axis than your base dimension.
To get started, open SQL Server Management Studio, and add a database TBC
, or if you are using Oracle you can add schema TBC
and use TOAD or Golden to complete the recipe.
Execute the following script to add the
Product
Table
. We can change the script below to PL/SQL by replacingint
with INTEGER andvarchar()
with VARCHAR2():--Create Product Table T-SQL create table PRODUCT ( PRODUCTID int not null, FAMILYID int null , SKU varchar(15) null , SKU_ALIAS varchar(25) null , CAFFEINATED varchar(5) null , OUNCES int null , PKGTYPE varchar(15) null , INTRODATE datetime null , constraint PK_PRODUCT primary key (PRODUCTID) ) Go
Execute the following queries to load data into the table you have just created. The SKUs do not repeat in this table, but as part of your discovery phase you should make sure that this is the case as duplicates will throw off your findings. The scripts that follow this step will help you do just that.
--Insert values into product table. This syntax should work with either Pl/SQL or T-SQL Insert into PRODUCT Values(1 , 1 , '100-10', 'Cola', 'TRUE', 12, 'Can', 'Mar 25 1996 12:00AM'); Insert into PRODUCT Values(2 , 1 , '100-20', 'Diet Cola', 'TRUE', 12, 'Can', 'Apr 1 1996 12:00AM'); Insert into PRODUCT Values(3 , 1 , '100-30', 'Caffeine Free Cola', 'FALSE', 16, 'Bottle', 'Apr 1 1996 12:00AM'); Insert into PRODUCT Values(4 , 2 , '200-10', 'Old Fashioned', 'TRUE', 12, 'Bottle', 'Sep 27 1995 12:00AM'); Insert into PRODUCT Values(5 , 2 , '200-20', 'Diet Root Beer', 'TRUE', 16, 'Bottle', 'Jul 26 1996 12:00AM'); Insert into PRODUCT Values(6 , 2 , '200-30', 'Sasparilla', 'FALSE', 12, 'Bottle', 'Dec 10 1996 12:00AM'); Insert into PRODUCT Values(7 , 2 , '200-40', 'Birch Beer', 'FALSE', 16, 'Bottle', 'Dec 10 1996 12:00AM'); Insert into PRODUCT Values(8 , 3 , '300-10', 'Dark Cream', 'TRUE', 20, 'Bottle', 'Jun 26 1996 12:00AM'); Insert into PRODUCT Values(9 , 3 , '300-20', 'Vanilla Cream', 'TRUE', 20, 'Bottle', 'Jun 26 1996 12:00AM'); Insert into PRODUCT Values(10, 3 , '300-30', 'Diet Cream', 'TRUE', 12, 'Can', 'Jun 26 1996 12:00AM'); Insert into PRODUCT Values(11, 4 , '400-10', 'Grape', 'FALSE', 32, 'Bottle', 'Oct 1 1996 12:00AM'); Insert into PRODUCT Values(12, 4 , '400-20', 'Orange', 'FALSE', 32, 'Bottle', 'Oct 1 1996 12:00AM'); Insert into PRODUCT Values(13, 4 , '400-30', 'Strawberry', 'FALSE', 32, 'Bottle', 'Oct 1 1996 12:00AM');
Execute the following script to determine the SKU count in the
PRODUCT
table:--Retrieve SKU count for both PL\SQL and T-SQL Select Count(SKU) From PRODUCT;
Execute the following scripts to determine the cardinality between the
SKU
and theCAFFEINATED
columns:--Determine if there is one-to-many relationship between SKU and Caffeinated for both PL\SQL and T-SQL Select SKU, Count(CAFFEINATED) As Cnt From PRODUCT Group By SKU Having Count(CAFFEINATED) = 1; Select CAFFEINATED, Count(SKU) As Cnt From PRODUCT T1 Group By CAFFEINATED;
Execute the following scripts to determine the cardinality between the
SKU
and theOUNCES
columns:--Determine if there is one-to-many relationship between SKU and Ounces for both PL\SQL and T-SQL Select SKU, Count(OUNCES) As Cnt From PRODUCT Group By SKU Having Count(OUNCES) = 1; Select OUNCES, Count(SKU) As Cnt From PRODUCT Group By OUNCES;
Execute the following scripts to determine the cardinality between the
SKU
andPKGTYPE
columns:--Determine if there is one-to-many relationship between SKU and PKGTYPE for both PL\SQL and T-SQL Select SKU, Count(PKGTYPE) As Cnt From PRODUCT Group By SKU Having Count(PKGTYPE) = 1; Select PKGTYPE, Count(SKU) As Cnt From PRODUCT Group By PKGTYPE;
Execute the following script to determine the cardinality between the
SKU
andINTRODATE
columns:--Determine if there is one-to-many relationship between SKU and IntroDate for both PL\SQL and T-SQL Select SKU, Count(INTRODATE) As Cnt From PRODUCT Group By SKU Having Count(INTRODATE) = 1; Select INTRODATE, Count(SKU) As Cnt From PRODUCT Group By INTRODATE;
Execute the following scripts to determine the cardinality between the
SKU
andPRODUCTID
columns:Execute the following scripts to determine the cardinality between the
PRODUCTID
andFAMILYID
columns:--Determine if there is one-to-many relationship between PRODUCTID and FAMILYID for both PL\SQL and T-SQL Select PRODUCTID, Count(FAMILYID) As Cnt From PRODUCT Group By PRODUCTID Having Count(PRODUCTID) = 1; Select FAMILYID, Count(PRODUCTID) As Cnt From PRODUCT Group By FAMILYID;
The first and second steps setup a Product
Table
and populate it with data. The third step retrieves a count of the SKU
s in your Product table. You will need this count to determine if the attribute column has a one-to-many relationship with the SKU
. This query returned exactly 13 valid SKU
s.
The first script in step 4 returns a row for every time the SKU
rolls up to one parent. You can see in the following screenshot, that there are exactly 13 rows signifying that each SKU
rolls up to one CAFFEINATED value.
This query returns the value, as shown in the following screenshot:
Select SKU, Count(CAFFEINATED) As Cnt From PRODUCT Group By SKU Having Count(CAFFEINATED) = 1;1;

The second script in step 4 shows you that the CAFFEINATED
column has a true and false value, which makes this column a good candidate for a Boolean attribute dimension. The reason this is a Boolean attribute is because it has exactly either of the two values TRUE or FALSE. The counts from this query and the previous one shows you that there are one-to-many relationships as SKUs rollup to only one CAFFEINATED value, but a single CAFFEINATED value can have many SKU children.
This script returns TRUE and FALSE values as depicted in the following screenshot:
Select CAFFEINATED, Count(SKU) As Cnt From PRODUCT T1 Group By CAFFEINATED;

The scripts in step 5 show a one-to-many relationship between SKU
and OUNCES
. Script 2 of step 5 shows that OUNCES
will make a good candidate for a NUMERIC attribute dimension. A NUMERIC attribute type is as the word implies a number. We can use a NUMERIC attribute's value in calculating scripts or outline formulas to create formulas based on the attribute assigned.
This query returns a list of numeric values as depicted in the following screenshot:
Select
OUNCES,
Count(SKU)
As
Cnt
From
PRODUCT
Group
By
OUNCES;

The scripts in step 6 show a one-to-many relationship between SKU
and PKGTYPE
as it returns exactly 13 unique records. Script 2 of step 6 shows the PKGTYPE
that would make a good TEXT
attribute or an alternate dimension. A
TEXT
attribute allows for a comparison in calculations and a selection of a member based on the attribute assigned. Text attributes are the default attribute in Essbase.
This query returns a list of text values as depicted in the following screenshot:
Select
PKGTYPE,
Count(SKU)
As
Cnt
From
PRODUCT
Group
By
PKGTYPE;

The scripts in step 7 also show a one-to-many relationship between SKU
and INTRODATE
. Script 2 of step 7 shows that INTRODATE
is, as the name implies, a date and as such will make a good DATE
attribute dimension. You can use DATE
attributes in calculation as well. We can compare different Products, for example, based on the DATE
attribute for specific Market. Date attributes from January 1, 1970 through January 1, 2038 are supported.
This query returns a list of date values as depicted in the following screenshot:
Select
INTRODATE,
Count(SKU)
As
Cnt
From
PRODUCT
Group
By
INTRODATE;

Moreover, in step 8 you will see a one-to-one relationship between SKU
and PRODUCTID
, which means there is exactly one PRODUCTID
for each SKU
, and one SKU
will rollup to exactly one parent. Script 2 of step 8 shows that this will more than likely be the main rollup in your PRODUCT
dimension. This is also intuitive as the SKU
in this case is the column representing the product:

Finally, the relationship between FAMILYID
and PRODUCTID
is a one-to-many relationship, shown in step 9. A possible outcome of these findings is to create a dimension and hiearchy with three generations as depicted in the following table:
DIMENSION |
GENERATION |
LEVEL |
---|---|---|
PRODUCT |
1 |
2 |
FAMILYID |
2 |
1 |
SKU |
3 |
0 |
In real world situations, you may come across scenarios where your relationships are not always one-to-one or one-to-many. Keep a note of these exceptions as you may need to concatenate columns, create alternate rollups with shared members, add a prefix or suffix, create a new dimension, or turn on duplicate members in your outline in order to deal with these issues. We will go over some of these in other chapters. That said, the preceding scripts will help you see these discrepancies before you begin building your cube, which will save you time later in your development. In addition, note that when building a BSO cube you can only assign attributes to a sparse dimension.
Refer to the recipes Adding attribute dimensions to hierarchies and Setting Essbase Properties in Chapter 3 to learn how to set up attribute dimensions and their properties in Essbase Studio.
In this recipe, we are going to use the Essbase Outline Extractor to extract the meta-data from the Sample Basic database in parent-child format. The Essbase Outline Extractor is a free product and can be downloaded from AppliedOLAP's website: http://www.appliedolap.com/free-tools/outline-extractor. The version you should consider for Essbase 11.1.2.1 for now is essbase_outline_extractor_11.1.2. This tool can assist you in extracting your metadata from an existing Essbase cube. We can then use its output to load Data Relationship Management (DRM) or a relational environment.
Click on Programs and select olapunderground | Essbase Outline Extractor | Essbase Outline Extractor.
Click on the Do not show this message again checkbox and click on Proceed if you get the following prompt:
You should now see the extract utility, as follows:
Click on the Login button on the top left and enter the server you want to log in to. Enter your username and password.
Click on the Sample.Basic application and database, and click on the OK button.
You should now have the option to select a dimension from the Select Dimension combo box. Click on the Product dimension.
Click on the Load File Format radio button and the Field Options command button. Select all the checkboxes except Currency Name/Category in this menu as it is not applicable in this case.
Click on the Browser button circled in the following screenshot and select a file location and filename.
You have the option to change the file's delimiter as well, but the exclamation mark (!) character should work fine.
A file should be produced in the location you specified, delimited by the bang or exclamation character, and in a parent-child format. The column headers in this file should be as follows:
COLUMN HEADERS
PARENT0,Product
CHILD0,Product
ALIAS0,Product
PROPERTY0,Product
FORMULA0,Product
OUNCES0,Product
CAFFEINATED0,Product
PKGTYPE0,Product
In this recipe, we will be using a third party tool called Star Integration Server Manager to build a star schema from an existing cube. The purpose of using this tool in this recipe is to quickly move the meta-data of your Essbase, Planning, or HFM applications to a relational environment. The tool we will be using is the express version and can be downloaded from the Star Analytics website: http://www.staranalytics.com/products/index.htm.
To get started, open Microsoft SQL Server and add a database called BASIC
. Microsoft SQL Server is being used for this example, but you can use Oracle, Sybase, Teradata, DB2, MySQL, or a text file to extract your outline.
Click on Programs and select Star Analytics | Star Integration Server Manager.
Double-click on Connection Manager on the left-hand side, and click on the New Connection button. The New HyperionEssbase Connection menu will appear on the screen, as follows:
Enter a Sample for your Connection Name and enter your Essbase Server.
Enter a Sample for the Application parameter value, Basic for the Database parameter value, Basic for your Outline parameter value, and your User Name and Password. Click on the Test button to test your connection, click the OK button on the pop up menu, and click on the Save and Close button.
Double-click on Connection Manager, select SQL Server using SQL Server login in the Connection Type, and enter Basic for the Name.
Enter your SQL Server name into the parameter value, Basic for the Database parameter, and enter your Login Name and Password.
Click on the Test button to test your connection, click the OK button on the popup menu, and click the Save and Close button.
Click on the New Essbase Selection button and select the Selection Information tab. In the Source Connection drop-down select Sample: Hyperion Essbase, and in the Target Connection drop-down select Basic: SQLServer-SQLLogin.
Check all the Export checkboxes in the Column Selections grid, and check on the Spin checkbox for Measures. Your screen will look like the following screenshot:
Click on the Run button in the Run Selection prompt and select Yes to run the Current Selection. Click on the OK button in the Run Completion on the pop up.
Verify that all your tables were created in the Running Essbase Selection in the local dialog box, and click on the Close button. Your screen should look as follows:
In this recipe, we created a connection to our relational database and a connection to Essbase. We then used the tool to define the dimensions we wanted to include in our star schema. Finally, we created a star schema using the Sample Basic database with our selections. You should see six tables in your Basic relational database. The results of this exercise are available in script 3265_01_08_tsql.sql
.
The Sample Basic database comes with the Essbase installation, but if you would like to build it, refer to the Adding an Application and Database on an Essbase server recipe in Chapter 5.