Skip Headers

Oracle® OLAP Developer's Guide to the OLAP API
10g Release 1 (10.1)

Part Number B10335-02
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Feedback

Go to previous page
Previous
Go to next page
Next
View PDF

7 Making Queries Using Source Methods

You create a query by producing a Source that specifies the data that you want to retrieve from the data store and any operations you want to perform on that data. To produce the query, you begin with the primary Source objects that represent the metadata of the measures and the dimensions and their attributes that you want to query. Typically, you use the methods of the primary Source objects to derive a number of other Source objects, each of which specifies a part of the query, such as a selection of dimension elements or an operation to perform on the data. You then join the primary and derived Source objects that specify the data and the operations that you want. The result is one Source that represents the query.

This chapter briefly describes the various kinds of Source methods, and discusses some of them in greater detail. It also discusses how to make some typical OLAP queries using these methods and provides examples of some of them.

This chapter includes the following topics:

For the complete code of the examples in this chapter, see the example programs available from the Overview of the Oracle OLAP Java API Reference.

7.1 Describing the Basic Source Methods

The Source class has many methods that return a derived Source. The elements of the derived Source result from operations on the base Source, which is the Source whose method is called that produces the derived Source. Only a few methods perform the most basic operations of the Source class.

The Source class has many other methods that use one or more of the basic methods to perform operations such as selecting elements of the base Source by value or by position, or sorting elements. Many of the examples in this chapter and in Chapter 6, " Understanding Source Objects" use some of these methods. Other Source methods get objects that have information about the Source, such as the getDefinition, getInputs, and getType methods, or convert the values of the Source from one data type to another, such as the toDoubleSource method.

This section describes the basic Source methods and provides some examples of their use. Table 7-1 lists the basic Source methods.

Table 7-1 The Basic Source Methods

Method Description
alias Produces a Source that has the same elements as its base Source, but has its base Source as its type.
distinct Produces a Source that has the same elements as its base Source, except that any elements that are duplicated in the base appear only once in the derived Source.
extract Produces a Source that has the same elements as its base Source, but that has its base Source as an extraction input.
join Produces a Source that has the elements of its base Source that are specified by the joined, comparison, and comparisonRule parameters of the method call. If the visible parameter is true, then the joined Source is an output of the resulting Source.
position Produces a Source that has the positions of the elements of its base Source, and that has its base Source as a regular input.
recursiveJoin Similar to the join method, except that this method, in the Source that it produces, orders the elements of the Source hierarchically by parent-child relationships.
value Produces a Source that has the same elements as its base Source, but that has its base Source as a regular input.

7.2 Using the Basic Methods

This section provides examples of using some of the basic methods.

7.2.1 Using the alias Method

You use the alias method to control the matching of a Source to an input. For example, if you want to find out if the measure values specified by an element of a dimension of the measure are greater than the measure values specified by the other elements of the same dimension, then you need to match the inputs of the measure twice in the same join operation. To do so, you can produce two Source objects that are aliases for the same dimension, make them inputs of two instances of the measure, join each measure instance to its aliased dimension, and then compare the results.

Example 7-1 performs such an operation. It produces a Source that specifies whether the number of units sold for each value of the channel dimension is greater than the number of units sold for the other values of the channel dimension.

The example joins to units, which is the Source for a measure, Source objects that are selections of single values of three of the dimensions of the measure to produce unitsSel. The unitsSel Source specifies the units elements for the dimension values that are specified by the timeSel, custSel, and prodSel objects, which are outputs of unitsSel.

The timeSel, custSel, and prodSel Source objects specify single values from the default hierarchies of the TIME, CUSTOMER, and PRODUCT dimensions, respectively. The timeSel value is CALENDAR::MONTH::55, which identifies the month January, 2001, the custSel value is SHIPMENTS_ROLLUP::SHIP_TO::52, which identifies the Business Word San Jose customer, and the prodSel value is PRODUCT_ROLLUP::ITEM::15, which identifies the Envoy Ambassador portable PC.

The example next creates two aliases, chanAlias1 and chanAlias2, for chanHier, which is the default hierarchy of the CHANNEL dimension. It then produces unitsSel1 by joining unitsSel to the Source that results from calling the value method of chanAlias1. The unitsSel1 Source has the elements and outputs of unitsSel and it has chanAlias1 as an input. Similarly, the example produces unitsSel2, which has chanAlias2 as an input.

The example uses the gt method of unitsSel1, which determines whether the values of unitsSel1 are greater than the values of unitsSel2. The following join operations matches chanAlias1 to the input of unitsSel1 and matches chanAlias1 to the input of unitsSel2.

Example 7-1 Controlling Input-to-Source Matching With the alias Method

Source unitsSel = units.join(timeSel).join(custSel).join(prodSel);
Source chanAlias1 = chanHier.alias();
Source chanAlias2 = chanHier.alias();
NumberSource unitsSel1 = (NumberSource)
                          unitsSel.join(chanAlias1.value());
NumberSource unitsSel2 = (NumberSource)
                          unitsSel.join(chanAlias2.value());
Source result = unitsSel1.gt(unitsSel2)
                         .join(chanAlias1)   // Output 2, column
                         .join(chanAlias2);  // Output 1, row;

The result Source specifies the query, "Are the units sold values of unitsSel1 for the channel values of chanAlias1 greater than the units sold values of unitsSel2 for the channel values of chanAlias2?" Because result is produced by the joining of chanAlias2 to the Source produced by unitsSel1.gt(unitsSel2).join(chanAlias1), chanAlias2 is the first output of result, and chanAlias1 is the second output of result.

A Cursor for the result Source has as its values the boolean values that answer the query. The values of the first output of the Cursor are the channel values specified by chanAlias2 and the values of its second output are the channel values specified by chanAlias1.

The following is a display of the values of the Cursor formatted as a crosstab with headings added. The column edge values are the values from chanAlias1, and the row edge values are the values from chanAlias2. The values of the crosstab cells are the boolean values that indicate whether the units sold value for the column channel value is greater than the units sold value for the row channel value. For example, the crosstab values in the first column indicate that the units sold for the column channel value All Channels is not greater than the units sold for the row All Channels value but it is greater than the units sold for the Direct Sales, Catalog, and Internet row values.

---------- chanAlias1 ----------
chanAlias2    All Channels  Direct Sales  Catalog  Internet
------------  ------------  ------------  -------  --------
All Channels       false       false       false    false
Direct Sales       true        false       true     false
Catalog            true        false       false    false
Internet           true        true        true     false

7.2.2 Using the distinct Method

You use the distinct method to produce a Source that does not have any duplicated values. Example 7-2 selects an element from a hierarchy of the CUSTOMER dimension and gets the descendants of that element. It then appends the descendants to the hierarchy element selection. Because the Source for the descendants includes the ancestor value, the example uses the distinct method to remove the duplicated ancestor value, which would otherwise appear twice in the result.

In Example 7-2, mktRollup is a StringSource that represents the MARKET_ROLLUP hierarchy of the CUSTOMER dimension. The mktRollupAncestors object is the Source for the ancestors attribute of that hierarchy. To get a Source that represents the descendents of the ancestors, the example uses the join method to select, for each element of mktRollupAncestors, the elements of mktRollup that have the mktRollupAncestors element as their ancestor. The join operation matches the base Source, mktRollup, to the input of the ancestors attribute.

The resulting Source, mktRollupDescendants, however, still has mktRollup as an input because the Source produced by the mktRollup.value() method is the comparison Source of the join operation. The comparison parameter Source of a join operation does not participate in the matching of an input to a Source.

The selectValue method of mktRollup selects the element of mktRollup that has the value MARKET_ROLLUP::ACCOUNT::23, which is the Business World account, and produces selVal. The join method of mktRollupDescendants uses selVal as the comparison parameter. The method produces selValDescendants, which is has the elements of mktRollupDescendants that are present in mktRollup, and that are also in selVal. The input of mktRollupDescendants is matched by the joined Source mktRollup. The mktRollup Source is not an output of selValDescendants because the value of the visible parameter of the join operation is false.

The appendValues method of selVal produces selValPlusDescendants, which is the result of appending the elements of selValDescendants to the element of selVal and then removing any duplicate elements with the distinct method.

Example 7-2 Using the distinct Method

Source mktRollupDescendants =
                     mktRollup.join(mktRollupAncestors, mktRollup.value());
Source selVal = mktRollup.selectValue("MARKET_ROLLUP::ACCOUNT::23");
Source selValDescendants = mktRollupDescendants.join(mktRollup,
                                                     selVal, 
                                                     false);
Source selValPlusDescendants = selVal.appendValues(selValDescendants)
                                     .distinct();

A Cursor for the selValPlusDescendants Source has the following values:

MARKET_ROLLUP::ACCOUNT::23
MARKET_ROLLUP::SHIP_TO::51
MARKET_ROLLUP::SHIP_TO::52
MARKET_ROLLUP::SHIP_TO::53
MARKET_ROLLUP::SHIP_TO::54

If the example did not include the distinct method call, then a Cursor for selValPlusDescendants would have the following values:

MARKET_ROLLUP::ACCOUNT::23
MARKET_ROLLUP::ACCOUNT::23
MARKET_ROLLUP::SHIP_TO::51
MARKET_ROLLUP::SHIP_TO::52
MARKET_ROLLUP::SHIP_TO::53
MARKET_ROLLUP::SHIP_TO::54

7.2.3 Using the extract Method

You use the extract method to extract the values of a Source that has Source objects as its element values. If the elements of a Source have element values that are not Source objects, the extract method operates like the value method.

Example 7-3 uses the extract method to get the values of the NumberSource objects that are themselves the values of the elements of measDim. Each of the NumberSource objects represents a measure. The first two are the primary NumberSource objects for the UNITS and the UNIT_PRICE measures, and the third is a NumberSource derived from a mathematical operation on the primary NumberSource objects.

The example selects values from hierarchies of the dimensions of the NumberSource for the UNITS measure. Two of the dimensions are the dimensions of the NumberSource for the UNIT_PRICE measure. The example produces sales, which is the result of the times method of units with unitPrice as the rhs parameter of the method.

Next, the example creates a list Source, measDim, which has the three NumberSource objects as its element values. It then uses the extract method to get the values of the NumberSource objects. The resulting unnamed Source has measDim as an extraction input. The input is matched by first join operation, which has measDim as the joined parameter. The example then matches the other inputs of the measures by joining the dimension selections to produce the result Source.

Example 7-3 Using the extract Method

Source prodSel = prodHier.selectValues(new String[]
                                        {"PRODUCT_ROLLUP::ITEM::13",
                                         "PRODUCT_ROLLUP::ITEM::14",
                                         "PRODUCT_ROLLUP::ITEM::15"});
Source chanSel = chanHier.selectValue("CHANNEL_ROLLUP::CHANNEL::2");
Source timeSel = timeHier.selectValue("CALENDAR::MONTH::59");
Source custSel = custHier.selectValue("SHIPMENTS_ROLLUP::ALL_CUSTOMERS::1");
 
Source sales = units.times(unitPrice);
 
Source measDim = dp.createListSource(new Source[] 
                                         {units, unitPrice, sales});
 
Source result = measDim.extract().join(measDim)   // column
                                 .join(prodSel)   // row
                                 .join(timeSel)   // page
                                 .join(chanSel)   // page
                                 .join(custSel);  // page

The following crosstab displays the values of a Cursor for the result Source, with headings and formatting added.

SHIPMENTS_ROLLUP::ALL_CUSTOMERS::1
CHANNEL_ROLLUP::CHANNEL::2
CALENDAR::MONTH::59
 
         UNITS SOLD   TOTAL OF UNIT PRICES   SALES AMOUNT
ITEM     ----------   --------------------   -------------
----
 13          39             2,395.63            93,429.57
 14          37             3,147.85           116,470.45
 15          26             2,993.29            77,825.54

7.2.4 Using the join Method

You use the join method to produce a Source that has the elements of its base Source that are determined by the joined, comparison, and comparisonRule parameters of the method. The visible parameter determines whether the joined Source is an output of the Source produced by the join operation. You also use the join method to match a Source to an input of the base or joined parameter Source.

The join method has many signatures that are convenient shortcuts for the full join(Source joined, Source comparison, int comparisonRule, boolean visible) method. The examples in this chapter use various join method signatures.

The Source class has several constants that you can provide as the value of the comparisonRule parameter. Example 7-4 and Example 7-5 demonstrate the use of two of those constants, COMPARISON_RULE_REMOVE and COMPARISON_RULE_DESCENDING. Example 7-6 also uses COMPARISON_RULE_REMOVE.

Example 7-4 produces a result similar to Example 7-2. It uses mktRollup, which is the Source for a hierarchy of the CUSTOMER dimension, and mktRollupAncestors, which is the Source for the ancestors attribute for the hierarchy. It also uses mktRollupDescendants, which is a Source for the descendants of elements of the hierarchy.

The example first selects an element of the hierarchy. Next, the join method of mktRollupDescendants produces mktRollupDescendantsOnly, which specifies the descendants of mktRollup, and which has mktRollup as an input because the comparison parameter of the join operation is the Source that results from the mktRollup.value() method.

Because COMPARISON_RULE_REMOVE is the comparison rule of the join operation that produced mktRollupDescendantsOnly, a join operation that matches a Source to the input of mktRollupDescendantsOnly produces a Source that has only those elements of mktRollupDescendantsOnly that are not in the comparison Source of the join operation.

The next join operation performs such a match. It matches the joined Source, mktRollup, to the input of mktRollupDescendantsOnly, to produce selValDescendantsOnly, which specifies the descendants of the selected hierarchy value but does not include the selected value because mktRollupDescendantsOnly specifies the removal of any values that match the value of the comparison Source, which is selVal.

As a contrast, the last join operation produces selValDescendants, which specifies the descendants of the selected hierarchy value and which does include the selected value.

Example 7-4 Using COMPARISON_RULE_REMOVE

Source selVal = mktRollup.selectValue("MARKET_ROLLUP::ACCOUNT::23");
Source mktRollupDescendantsOnly = 
      mktRollupDescendants.join(mktRollupDescendants.getDataType().value(),
                                mktRollup.value(), 
                                Source.COMPARISON_RULE_REMOVE);

// Select the descendants of the specified element.
Source selValDescendants = mktRollupDescendants.join(mktRollup, selVal);

// Select only the descendants of the specified element.
Source selValDescendantsOnly = mktRollupDescendantsOnly.join(mktRollup,
                                                                   selVal);

A Cursor for selValDescendants has the following values.

MARKET_ROLLUP::ACCOUNT::23
MARKET_ROLLUP::SHIP_TO::51
MARKET_ROLLUP::SHIP_TO::52
MARKET_ROLLUP::SHIP_TO::53
MARKET_ROLLUP::SHIP_TO::54

A Cursor for selValDescendantsOnly has the following values.

MARKET_ROLLUP::SHIP_TO::51
MARKET_ROLLUP::SHIP_TO::52
MARKET_ROLLUP::SHIP_TO::53
MARKET_ROLLUP::SHIP_TO::54

Example 7-5 demonstrates another join operation, which uses the comparison rule COMPARISON_RULE_DESCENDING. It uses the following Source objects.

  • prodSelWithShortDescr, which is the Source produced by joining the Source for the short value description attribute of the PRODUCT dimension to the Source for the FAMILY level of the PRODUCT_ROLLUP hierarchy of that dimension.

  • unitPrice, which is the Source for the UNIT_PRICE measure.

  • timeSelWithShortDescr, which is the Source produced by joining the Source for the short value description attribute of the TIME dimension to the Source for a selected element of the CALENDAR hierarchy of that dimension.

The resulting Source specifies the product family level elements in descending order of total unit prices for the month of May, 2001.

Example 7-5 Using COMPARISON_RULE_DESCENDING

Source result = 
       prodSelWithShortDescr.join(unitPrice,
                                  unitPrice.getDataType(),
                                  Source.COMPARISON_RULE_DESCENDING,
                                  true)
                            .join(timeSelWithShortDescr);

A Cursor for the result Source has the following values, displayed as a table. The table includes only the short value descriptions of the dimension elements and the unit price values, and has formatting added.

May, 2001
 
Total Unit Prices   Product Family
-----------------   --------------
 
     8,536.77       Portable PCs
     5,613.08       Desktop PCs
     1,273.00       CD-ROM
       830.74       Memory
       795.24       Monitors
       448.06       Documentation
       364.93       Accessories
       318.61       Modems/Fax
       131.84       Operating Systems

7.2.5 Using the position Method

You use the position method to produce a Source that has the positions of the elements of its base and has the base as an input. Example 7-6 uses the position method in producing a Source that specifies the selection of the first and last elements of the levels of a hierarchy of the TIME dimension.

In the example, mdmTimeDim is the MdmPrimaryDimension for the TIME dimension. The example gets the level attribute and the default hierarchy of the dimension. It then gets Source objects for the attribute and the hierarchy.

Next, the example creates an array of Source objects and gets a List of the MdmLevel components of the hierarchy. It gets the Source object for each level and adds it to the array, and then creates a list Source that has the Source objects for the levels as its element values.

The example then produces levelMembers, which is a Source that specifies the elements of the levels of the hierarchy. Because the comparison parameter of the join operation is the Source produced by levelList.value(), levelMembers has levelList as an input. Therefore, levelMembers is a Source that returns the elements of each level, by level, when its input is matched in a join operation.

The range Source specifies a range of elements from the second element to the next to last element of a Source.

The next join operation produces the firstAndLast Source. The base of the operation is levelMembers. The joined parameter is the Source that results from the levelMembers.position() method. The comparison parameter is the range Source and the comparison rule is COMPARISON_RULE_REMOVE. The value of the visible parameter is true. The firstAndLast Source therefore specifies only the first and last elements of the levels because it removes all of the other elements of the levels from the selection. The firstAndLast Source still has levelList as an input.

The final join operation matches the input of firstAndLast to levelList.

Example 7-6 Selecting the First and Last Time Elements

MdmAttribute mdmTimeLevelAttr = mdmTimeDim.getLevelAttribute();
MdmLevelHierarchy mdmTimeHier = (MdmLevelHierarchy)
                                 mdmTimeDim.getDefaultHierarchy();

Source levelRel = mdmTimeLevelAttr.getSource();
StringSource calendar = (StringSource) mdmTimeHier.getSource();

Source[] levelSources = new Source[3];
List levels = mdmTimeHier.getLevels();
for (int i = 0; i < levelSources.length; i++)
{
  levelSources[i] = ((MdmLevel) levels.get(i)).getSource();
}
Source levelList = dp.createListSource(levelSources);
Source levelMembers =  calendar.join(levelRel, levelList.value());
Source range = dp.createRangeSource(2, levelMembers.count().minus(1)); 
Source firstAndLast = levelMembers.join(levelMembers.position(),
                                        range
                                        Source.COMPARISON_RULE_REMOVE,
                                        true);
 
Source result = firstAndLast.join(levelList);

A Cursor for the result Source has the following values, displayed as a table with column headings and formatting added. The left column names the level, the middle column is the position of the element in the level, and the right column is the local value of the element.

Level  Level Position  Level Value
-----  --------------  -----------
YEAR          1              1
YEAR          7            119
QUARTER       1              5
QUARTER      26            116
MONTH         1             19
MONTH        77            107

7.2.6 Using the recursiveJoin Method

You use the recursiveJoin method to produce a Source that has its elements ordered hierarchically. You use the recursiveJoin method only with the Source for an MdmHierarchy or on a subtype of such a Source. The method produces a Source whose elements are ordered hierarchically by the parents and their children in the hierarchy.

Like the join method, you use the recursiveJoin method to produce a Source that has the elements of its base Source that are determined by the joined, comparison, and comparisonRule parameters of the method. The visible parameter determines whether the joined Source is an output of the Source produced by the recursive join operation.

The recursiveJoin method has several signatures. The full recursiveJoin method has parameters that specify the parent attribute of the hierarchy, whether the result should have the parents before or after their children, how to order the elements of the result if the result includes children but not the parent, and whether the joined Source is an output of the resulting Source.

Example 7-7 uses a recursiveJoin method that lists the parents first, restricts the parents to the base, and does not add the joined Source is an output. The example first sorts the elements of a hierarchy of the PRODUCT dimension by hierarchical levels and then by the value of the color attribute of each element.

The first recursiveJoin method orders the elements of the prodRollup hierarchy in ascending hierarchical order. The prodParent object is the Source for the parent attribute of the hierarchy.

The prodColorAttr object in the second recursiveJoin method is the Source for a color attribute of the hierarchy. Only the elements of the ITEM level of the hierarchy have a related color value. Because the elements in the aggregate levels TOTAL_PRODUCT, CLASS, and FAMILY, do not have related colors, the color attribute value for elements in those levels is null, which appears as NA in the results. Some of the ITEM level elements do not have a related color, so their values are NA, also.

The second recursiveJoin method joins the color attribute values to their related hierarchy elements and sorts the elements hierarchically by level, and then sorts them in ascending order in the level by the color value. The COMPARISON_RULE_ASCENDING_NULLS_FIRST parameter specifies that elements that have a null value appear before the other elements in the same level. The example then joins the result of the method, sortedHierNullsFirst, to the color attribute to produce a Source that has the color values as its element values and sortedHierNullsFirst as an output.

The third recursiveJoin method is the same as the second, except that the COMPARISON_RULE_ASCENDING_NULLS_LAST parameter specifies that elements that have a null value appear after the other elements in the same level.

Example 7-7 Sorting Products Hierarchically By Color

Source result1 = 
         prodRollup.recursiveJoin(prodDim.value(),
                                  prodRollup.getDataType(),
                                  prodParent,
                                  Source.COMPARISON_RULE_ASCENDING);

Source sortedHierNullsFirst = 
 prodRollup.recursiveJoin(prodColorAttr,
                          prodColorAttr.getDataType(),
                          prodParent,
                          Source.COMPARISON_RULE_ASCENDING_NULLS_FIRST);
Source result2 = prodColorAttr.join(sortedHierNullsFirst);

Source sortedHierNullsLast = 
 prodRollup.recursiveJoin(prodColorAttr,
                          prodColorAttr.getDataType(),
                          prodParent,
                          Source.COMPARISON_RULE_DESCENDING_NULLS_LAST);
Source result3 = prodColorAttr.join(sortedHierNullsLast); 

A Cursor for the result1 Source has the following values, displayed with a heading added. The list contains only the first ten values of the Cursor.

Product Dimension Element Value
--------------------------------
PRODUCT_ROLLUP::TOTAL_PRODUCT::1
PRODUCT_ROLLUP::CLASS::2
PRODUCT_ROLLUP::FAMILY::4
PRODUCT_ROLLUP::ITEM::13
PRODUCT_ROLLUP::ITEM::14
PRODUCT_ROLLUP::ITEM::15
PRODUCT_ROLLUP::FAMILY::5
PRODUCT_ROLLUP::ITEM::16
PRODUCT_ROLLUP::ITEM::17
PRODUCT_ROLLUP::ITEM::18
...

A Cursor for the result2 Source has the following values, displayed as a table with headings added. The table contains only the first ten values of the Cursor. The left column has the element values of the hierarchy, and the right column has the color attribute value for the element.

The ITEM level elements that have a null value appear first, and then the other level elements appear in ascending order of color value. Since the data type of the color attribute is String, the color values are in ascending alphabetical order.

Product Dimension Element Value   Color Value
-------------------------------   -----------
PRODUCT_ROLLUP::TOTAL_PRODUCT::1     NA
PRODUCT_ROLLUP::CLASS::2             NA
PRODUCT_ROLLUP::FAMILY::4            NA
PRODUCT_ROLLUP::ITEM::14             NA
PRODUCT_ROLLUP::ITEM::15             Black
PRODUCT_ROLLUP::ITEM::13             Silver
PRODUCT_ROLLUP::FAMILY::5            NA
PRODUCT_ROLLUP::ITEM::18             NA
PRODUCT_ROLLUP::ITEM::17             Beige
PRODUCT_ROLLUP::ITEM::16             Silver
...

A Cursor for the result3 Source has the following values, displayed as a table with headings added. This time the elements are in descending order, alphabetically by color attribute value.

Product Dimension Element Value   Color Value
-------------------------------   -----------
PRODUCT_ROLLUP::TOTAL_PRODUCT::1     NA
PRODUCT_ROLLUP::CLASS::2             NA
PRODUCT_ROLLUP::FAMILY::4            NA
PRODUCT_ROLLUP::ITEM::14             NA
PRODUCT_ROLLUP::ITEM::13             Silver
PRODUCT_ROLLUP::ITEM::15             Black
PRODUCT_ROLLUP::FAMILY::5            NA
PRODUCT_ROLLUP::ITEM::18             NA
PRODUCT_ROLLUP::ITEM::16             Silver
PRODUCT_ROLLUP::ITEM::17             Beige
...

7.2.7 Using the value Method

You use the value method to create a Source that has itself as an input. That relationship enables you to select a subset of elements of the Source.

Example 7-8 demonstrates the selection of such a subset. In the example, shipRollup is a Source for the SHIPMENTS_ROLLUP hierarchy of the CUSTOMER dimension. The selectValues method of shipRollup produces custSel, which is a selection of some of the elements of shipRollup. The selectValues method of custSel produces custSel2, which is a subset of that selection.

The first join method has custSel as the base and as the joined Source. It has custSel2 as the comparison Source. The elements of the resulting Source, result1, are one set of the elements of custSel for each element of custSel that is in the comparison Source. The true value of the visible parameter causes the joined Source to be an output of result1.

The second join method also has custSel as the base and custSel2 as the comparison Source, but it has the result of the custSel.value() method as the joined Source. Because custSel is an input of the joined Source, the base Source matches that input. That input relationship causes the resulting Source, result2, to have only those elements of custSel that are also in the comparison Source.

Example 7-8 Selecting a Subset of the Elements of a Source

StringSource custSel = (StringSource) shipRollup.selectValues(new String[]
                                           {"SHIPMENTS_ROLLUP::SHIP_TO::60",
                                            "SHIPMENTS_ROLLUP::SHIP_TO::61",
                                            "SHIPMENTS_ROLLUP::SHIP_TO::62",
                                            "SHIPMENTS_ROLLUP::SHIP_TO::63"});

Source custSel2 = custSel.selectValues(new String[]
                                        {"SHIPMENTS_ROLLUP::SHIP_TO::60",
                                         "SHIPMENTS_ROLLUP::SHIP_TO::62"});
 
Source result1 = custSel.join(custSel, custSel2, true);
 
Source  result2 = custSel.join(custSel.value(), custSel2, true);

A Cursor for result1 has the following values, displayed as a table with headings added. The left column has the values of the elements of the output of the Cursor. The right column has the values of the Cursor.

Output Value                    result1 Value        
-----------------------------   -----------------------------
SHIPMENTS_ROLLUP::SHIP_TO::60   SHIPMENTS_ROLLUP::SHIP_TO::60
SHIPMENTS_ROLLUP::SHIP_TO::60   SHIPMENTS_ROLLUP::SHIP_TO::61
SHIPMENTS_ROLLUP::SHIP_TO::60   SHIPMENTS_ROLLUP::SHIP_TO::62
SHIPMENTS_ROLLUP::SHIP_TO::60   SHIPMENTS_ROLLUP::SHIP_TO::63
SHIPMENTS_ROLLUP::SHIP_TO::62   SHIPMENTS_ROLLUP::SHIP_TO::60
SHIPMENTS_ROLLUP::SHIP_TO::62   SHIPMENTS_ROLLUP::SHIP_TO::61
SHIPMENTS_ROLLUP::SHIP_TO::62   SHIPMENTS_ROLLUP::SHIP_TO::62
SHIPMENTS_ROLLUP::SHIP_TO::62   SHIPMENTS_ROLLUP::SHIP_TO::63

A Cursor for result2 has the following values, displayed as a table with headings added. The left column has the values of the elements of the output of the Cursor. The right column has the values of the Cursor.

Output Value                    result2 Value        
-----------------------------   -----------------------------
SHIPMENTS_ROLLUP::SHIP_TO::60   SHIPMENTS_ROLLUP::SHIP_TO::60
SHIPMENTS_ROLLUP::SHIP_TO::62   SHIPMENTS_ROLLUP::SHIP_TO::62

7.3 Using Other Source Methods

Along with the methods that are various signatures of the basic methods, the Source class has many other methods that use combinations of the basic methods. Some methods perform selections based on a single position, such as the at and offset methods. Others operate on a range of positions, such as the interval method. Some perform comparisons, such as eq and gt, select one or more elements, such as selectValue or removeValue, or sort elements, such as sortAscending or sortDescendingHierarchically.

The subclasses of Source each have other specialized methods, also. For example, the NumberSource class has many methods that perform mathematical functions such as abs, div, and cos, and methods that perform aggregations, such as average and total.

This section has examples that demonstrate the use of some of the Source methods. Some of the examples are tasks that an OLAP application typically performs.

7.3.1 Creating a Cube and Pivoting Edges

One typical OLAP operation is the creation of a cube, which is a multi-dimensional array of data. The data of the cube is specified by the elements of the column, row, and page edges of the cube. The data of the cube can be data from a measure that is specified by the elements of the dimensions of the measure. The cube data can also be dimension elements that are specified by some calculation of the measure data, such as products that have unit sales quantities greater than a specified amount.

Most of the examples in this section create cubes. Example 7-9 creates a cube that has the quantity of units sold as its data. The column edge values are initially from a channel dimension hierarchy, the row edge values are from a time dimension hierarchy, and the page edge values of the cube are from elements of hierarchies for product and customer dimensions. The product and customer elements on the page edge are represented by parameterized Source objects.

The example joins the selections of the dimension elements to the short value description attributes for the dimensions so that the results have more information than just the numerical identifications of the dimension values. It then joins the Source objects derived from the dimensions to the Source for the measure to produce the cube query. It prepares and commits the current Transaction, and then creates a Cursor for the query and displays its values.

After displaying the values of the Cursor, the example changes the value of the Parameter for the parameterized Source for the customer selection, thereby retrieving a different result set using the same Cursor in the same Transaction. The example resets the position of the Cursor, and displays the values of the Cursor again.

The example then pivots the column and row edges so that the column values are time elements and the row values are channel elements. It prepares and commits the Transaction, creates another Cursor for the query, and displays its values. It then changes the value of each Parameter object and displays the values of the Cursor again.

The dp object is the DataProvider. The context object has a method that displays the values of the Cursor in a crosstab format.

Example 7-9 Creating a Cube and Pivoting Its Edges

// Create Parameter objects with values from the default hierarchies
// of the CUSTOMER and PRODUCT dimensions.
StringParameter custParam =
                      new StringParameter(dp, "SHIPMENTS_ROLLUP::REGION::9");
StringParameter prodParam =
                      new StringParameter(dp, "PRODUCT_ROLLUP::FAMILY::4");
                      
// Create parameterized Source objects using the Parameter objects.
StringSource custParamSrc = dp.createParameterizedSource(custParam);    
StringSource prodParamSrc = dp.createParameterizedSource(prodParam);

// Select single values from the hierarchies, using the Parameter
// objects as the comparisons in the join operations.
Source paramCustSel = custHier.join(custHier.value(), custParamSrc);
Source paramProdSel = prodHier.join(prodHier.value(), prodParamSrc);

// Select elements from the other dimensions of the measure
Source timeSel = timeHier.selectValues(new String[] 
                                              {"CALENDAR::YEAR::2"
                                               "CALENDAR::YEAR::3",
                                               "CALENDAR::YEAR::4"});
Source chanSel = chanHier.selectValues(new String[] 
                                     {"CHANNEL_ROLLUP::CHANNEL::2",
                                      "CHANNEL_ROLLUP::CHANNEL::3",
                                      "CHANNEL_ROLLUP::CHANNEL::4"});

// Join the dimension selections to the short description attributes
// for the dimensions.
Source columnEdge = chanSel.join(chanShortDescr);
Source rowEdge = timeSel.join(timeShortDescr);
Source page1 = paramProdSel.join(prodShortDescr);
Source page2 = paramCustSel.join(custShortDescr);

// Join the dimension selections to the measure.
Source cube = units.join(columnEdge)
                   .join(rowEdge)
                   .join(page2)
                   .join(page1);

// Get the TransactionProvider.
TransactionProvider tp = context.getTransactionProvider();
// Prepare and commit the currentTransaction.   
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot prepare the current Transaction. " + e
}
tp.commitCurrentTransaction();

// Create a Cursor for the query.
CursorManagerSpecification cMngrSpec = 
                        dp.createCursorManagerSpecification(cube);
SpecifiedCursorManager  spCMngr = dp.createCursorManager(cMngrSpec);
Cursor cubeCursor = spCMngr.createCursor();
// Display the values of the Cursor as a crosstab.
context.displayCursorAsCrosstab(cubeCursor);

// Change the customer parameter value.
custParam.setValue("SHIPMENTS_ROLLUP::REGION::10");

// Reset the Cursor position to 1 and display its values again.
cubeCursor.setPosition(1);
context.println(" ");
context.displayCursorAsCrosstab(cubeCursor);

// Pivot the column and row edges.
columnEdge = timeSel.join(timeShortDescr);
rowEdge = chanSel.join(chanShortDescr);

// Join the dimension selections to the measure.
cube = units.join(columnEdge)
            .join(rowEdge))
            .join(page2)
            .join(page1);
 
// Prepare and commit the current Transaction.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot prepare the current Transaction. " + e);
}
tp.commitCurrentTransaction();

// Create another Cursor.
cMngrSpec = dp.createCursorManagerSpecification(cube);
spCMngr = dp.createCursorManager(cMngrSpec);
cubeCursor = spCMngr.createCursor();
context.displayCursorAsCrosstab(cubeCursor);

// Change the product parameter value.
prodParam.setValue("PRODUCT_ROLLUP::FAMILY::5");

// Reset the Cursor position to 1
cubeCursor.setPosition(1);
context.println(" ");
context.displayCursorAsCrosstab(cubeCursor);

The following crosstab has the values of cubeCursor displayed by the first displayCursorAsCrosstab method.

Portable PCs
Europe
 
        Direct Sales  Catalog  Internet
1999              86     1986        0
2000             193     1777       10
2001             196     1449      215
 

The following crosstab has the values of cubeCursor after the example changed the value of the custParam Parameter object.

Portable PCs
North America

        Direct Sales  Catalog  Internet
1999             385     6841        0
2000             622     6457       35
2001             696     5472      846

The next crosstab has the values of cubeCursor after pivoting the column and row edges.

Portable PCs
North America
 
                1999    2000    2001
Direct Sales     385     622     696
Catalog         6841    6457    5472
Internet           0      35     846

The last crosstab has the values of cubeCursor after changing the value of the prodParam Parameter object.

Desktop PCs
North America
 
                1999    2000    2001
Direct Sales     793    1224    1319
Catalog        14057    1321   11337
Internet           0      69    1748

7.3.2 Drilling Up and Down in a Hierarchy

Drilling up or down in a dimension hierarchy is another typical OLAP operation. Example 7-10 demonstrates getting the elements of one level of a dimension hierarchy, selecting an element, and then getting the parent, children, and ancestors of the element.

The example uses the following objects.

  • levelSrc, which is the Source for the FAMILY level of the PRODUCT_ROLLUP hierarchy of the PRODUCT dimension.

  • prodRollup, which is the Source for the PRODUCT_ROLLUP hierarchy.

  • prodRollupParentAttr, which is the Source for the parent attribute of the hierarchy.

  • prodRollupAncsAttr, which is the Source for the ancestors attribute of the hierarchy.

  • prodShortLabel, which is the Source for the short value description attribute of the PRODUCT dimension.

  • context, which has methods that prepare and commit the current Transaction, that create a Cursor for a Source, that display text, and that display the values of the Cursor.

Example 7-10 Drilling in a Hierarchy

int pos = 2;
// Get the element at the specified position of the level Source.
Source levelElement = levelSrc.at(pos);

// Select the element of the hierarchy with the specified value.
Source levelSel = prodRollup.join(prodRollup.value(), levelElement);

// Get ancestors of the level element.
Source levelElementAncs = prodRollupAncsAttr.join(prodRollup,
                                                  levelElement);
// Get the parent of the level element.
Source levelElementParent = prodRollupParentAttr.join(prodRollup,
                                                      levelElement);
// Get the children of a parent.
Source prodRollupChildren = prodRollup.join(prodRollupParentAttr,
                                            prodRollup.value());

// Select the children of the level element.
Source levelElementChildren = prodRollupChildren.join(prodRollup,
                                                      levelElement);

// Get the short value descriptions for the elements of the level.
Source levelSrcWithShortDescr = prodShortLabel.join(levelSrc);

// Get the short value descriptions for the children.
Source levelElementChildrenWithShortDescr =
                               prodShortLabel.join(levelElementChildren);

// Get the short value descriptions for the parents.
Source levelElementParentWithShortDescr = 
               prodShortLabel.join(prodRollup, levelElementParent, true);

// Get the short value descriptions the ancestors.
Source levelElementAncsWithShortDescr = 
            prodShortLabel.join(prodRollup, levelElementAncs, true);

// Prepare and commit the current Transaction.
context.commit();

// Create Cursor objects and display their values.
context.println("Level element values:");
context.displayResult(levelSrcWithShortDescr);
context.println("\nLevel element at position " + pos + ":");
context.displayResult(levelElement);
context.println("\nParent of the level element:");
context.displayResult(levelElementParent);
context.println("\nChildren of the level element:");
context.displayResult(levelElementChildrenWithShortDescr);
context.println("\nAncestors of the level element:");
context.displayResult(levelElementAncs);

The following list has the values of the Cursor objects created by the displayResults methods.

Level element values:
 
1: (PRODUCT_ROLLUP::FAMILY::4,Portable PCs)
2: (PRODUCT_ROLLUP::FAMILY::5,Desktop PCs)
3: (PRODUCT_ROLLUP::FAMILY::6,Operating Systems)
4: (PRODUCT_ROLLUP::FAMILY::7,Accessories)
5: (PRODUCT_ROLLUP::FAMILY::8,Monitors)
6: (PRODUCT_ROLLUP::FAMILY::9,Modems/Fax)
7: (PRODUCT_ROLLUP::FAMILY::10,Memory)
8: (PRODUCT_ROLLUP::FAMILY::11,CD-ROM)
9: (PRODUCT_ROLLUP::FAMILY::12,Documentation)
 
Level element at position 2:
 
1: PRODUCT_ROLLUP::FAMILY::5
 
Parent of the level element:
 
1: (PRODUCT_ROLLUP::CLASS::2,Hardware)
 
Children of the level element:
 
1: (PRODUCT_ROLLUP::ITEM::16,Sentinel Standard)
2: (PRODUCT_ROLLUP::ITEM::17,Sentinel Financial)
3: (PRODUCT_ROLLUP::ITEM::18,Sentinel Multimedia)
 
Ancestors of the level element:
 
1: (PRODUCT_ROLLUP::TOTAL_PRODUCT::1,Total Product)
2: (PRODUCT_ROLLUP::CLASS::2,Hardware)
3: (PRODUCT_ROLLUP::FAMILY::5,Desktop PCs)

7.3.3 Sorting Hierarchically by Measure Values

Example 7-11 uses the recursiveJoin method to sort the elements of the PRODUCT_ROLLUP hierarchy of the PRODUCT dimension hierarchically in ascending order of the values of the UNITS measure. The example joins the sorted products to the short value description attribute of the dimension, and then joins the result of that operation, sortedProductsShortDescr, to units.

The successive joinHidden methods join the selections of the other dimensions of units to produce the result Source, which has the measure data as its element values and sortedProductsShortDescr as its output. The example uses the joinHidden methods so that the other dimension selections are not outputs of the result.

The example uses the following objects.

  • prodRollup, which is the Source for the PRODUCT_ROLLUP hierarchy.

  • units, which is the Source for the UNITS measure of product units sold.

  • prodParent, which is the Source for the parent attribute of the PRODUCT_ROLLUP hierarchy.

  • prodRollupAncsAttr, which is the Source for the ancestors attribute of the hierarchy.

  • prodShortDescr, which is the Source for the short value description attribute of the PRODUCT dimension.

  • custSel, which is a Source that specifies a single element of the default hierarchy of the CUSTOMER dimension. Its value is SHIPMENTS_ROLLUP::ALL_CUSTOMERS::1, which is all customers.

  • chanSel, which is a Source that specifies a single element of the default hierarchy of the CHANNEL dimension. Its value is CHANNEL_ROLLUP::CHANNEL::2, which is the direct sales channel.

  • timeSel, which is a Source that specifies a single element of the default hierarchy of the TIME dimension. Its value is CALENDAR::YEAR::4, which is the year 2001.

Example 7-11 Hierarchical Sorting by Measure Value

Source sortedProduct =
          prodRollup.recursiveJoin(units,
                                   units.getDataType(),
                                   prodParent,
                                   Source.COMPARISON_RULE_ASCENDING,
                                   true,  // Parents first
                                   true); // Restrict parents to base
 
Source sortedProductShortDescr = prodShortDescr.join(sortedProduct);
Source result = units.join(sortedProductShortDescr)
                     .joinHidden(custSel)
                     .joinHidden(chanSel)
                     .joinHidden(timeSel);

A Cursor for the result Source has the following values, displayed in a table with column headings and formatting added. The left column has the name of the level in the PRODUCT_ROLLUP hierarchy. The next column to the right has the product identification value, and the next column has the short value description of the product. The rightmost column has the number of units of the product sold to all customers in the year 2001 through the direct sales channel.

The table contains only the first nine and the last ten values of the Cursor, plus the Software/Other class value. The product values are listed in hierarchical order by units sold. The Hardware class appears before the Software/Other class because the Software/Other class has a greater number of units sold. In the Hardware class, the Monitors family sold the fewest units, so it appears first. In the Software/Other class, the Accessories family has the greatest number of units sold, so it appears last.

Product Level ID Description                  Units Sold
------------- -- ---------------------------- ----------
 
TOTAL_PRODUCT  1 Total Product                    43,783
        CLASS  2 Hardware                         16,541
       FAMILY  4 Portable PCs                      1,192
         ITEM 15 Envoy Ambassador                    330
         ITEM 14 Envoy Executive                     385
         ITEM 13 Envoy Standard                      477
       FAMILY  8 Monitors                          1,193
         ITEM 21 Monitor- 19 Super VGA               207
         ITEM 20 Monitor- 15 Super VGA               986
         ...
        CLASS 3 Software/Other                   27,242
         ...
       FAMILY  7 Accessories                      18,949
         ITEM 22 Envoy External Keyboard             146
         ITEM 23 External 101-key keyboard           678
         ITEM 32 Multimedia speakers- 5 cones        717
         ITEM 46 Standard Mouse                      868
         ITEM 27 Multimedia speakers- 3 cones      1,120
         ITEM 31 1.44MB External 3.5 Diskette      1,145
         ITEM 48 Keyboard Wrist Rest               2,231
         ITEM 19 Laptop carrying case              3,704
         ITEM 47 Deluxe Mouse                      3,884
         ITEM 30 Mouse Pad                         4,456

7.3.4 Using NumberSource Methods To Compute the Share of Units Sold

Example 7-12 uses the NumberSource methods div and times to produce a Source that specifies the share that the Desktop PC and Portable PC families have of the total quantity of product units sold for the selected time, customer, and channel values. The example first uses the selectValue method of prodRollup, which is the Source for a hierarchy of the PRODUCT dimension, to produce allProds, which specifies a single element with the value PRODUCT_ROLLUP::TOTAL_PRODUCT::1, which is the highest aggregate level of the hierarchy.

The joinHidden method of the NumberSource units produces totalUnits, which specifies the UNITS measure values at the total product level, without having allProds appear as an output of totalUnits. The div method of units then produces a Source that represents each units sold value divided by total quantity of units sold. The times method then multiplies the result of that div operation by 100 to produce productShare, which represents the percentage, or share, that a product element has of the total quantity of units sold. The productShare Source has the inputs of the units measure as its inputs.

The prodFamilies object is the Source for the FAMILY level of the PRODUCT_ROLLUP hierarchy. The join method of productShare, with prodFamilies as the joined Source, produces a Source that specifies the share that each product family has of the total quantity of products sold.

The custSel, chanSel, and timeSel Source objects are selections of single elements of hierarchies of the CUSTOMER, CHANNEL, and TIME dimensions. The remaining join methods match those Source objects to the other inputs of productShare, to produce result. The join(Source joined, String comparison) signature of the join method produces a Source that does not have the joined Source as an output.

The result Source specifies the share for each product family of the total quantity of products sold to all customers through the direct sales channel in the year 2001.

Example 7-12 Getting the Share of Units Sold

Source allProds = prodRollup.selectValue("PRODUCT_ROLLUP::TOTAL_PRODUCT::1");
NumberSource totalUnits = (NumberSource) units.joinHidden(allProds);
Source productShare = units.div(totalUnits).times(100);
Source result = 
      productShare.join(prodFamilies)
                  .join(timeHier, "CALENDAR::YEAR::4")
                  .join(chanHier, "CHANNEL_ROLLUP::CHANNEL::2")
                  .join(custHier, "SHIPMENTS_ROLLUP::ALL_CUSTOMERS::1");

A Cursor for the result Source has the following values, displayed in a table with column headings and formatting added. The left column has the product family value and the right column has the share of the total number of units sold for the product family to all customers through the direct sales channel in the year 2001.

Product Family Element      Share of Total Units Sold
-------------------------   -------------------------
PRODUCT_ROLLUP::FAMILY::4             2.72%
PRODUCT_ROLLUP::FAMILY::5             5.13%
PRODUCT_ROLLUP::FAMILY::6            12.54%
PRODUCT_ROLLUP::FAMILY::7            43.28%
PRODUCT_ROLLUP::FAMILY::8             2.73%
PRODUCT_ROLLUP::FAMILY::9            11.92%
PRODUCT_ROLLUP::FAMILY::10            3.57%
PRODUCT_ROLLUP::FAMILY::11           11.71%
PRODUCT_ROLLUP::FAMILY::12            6.4%

7.3.5 Ranking Dimension Elements by Measure Value

Example 7-13 produces two results. The first is result1, which is a Source that specifies the rank of two families of products and their members in the order of the sales of all product units. The second is result2, which ranks those families and their members by quantity of units sold compared to each other.

The units object is the Source for the UNITS measure, and prodRollup is the Source for the PRODUCT_ROLLUP hierarchy of the PRODUCT dimension. The join method of units produces a Source that specifies units sold values for each element of the hierarchy.

The select method has as its filter parameter the BooleanSource produced by the gt method of the Source that results from the units.value() method. The Source that results from the select method has units as an input. When a join operation matches a Source to that input, it produces a Source that, for each element of the units measure, has the Boolean value true for every units sold value that is greater than the current element value.

The count method then produces a Source that has, for each element of the measure, the total number of all the products that have greater sales quantities. The product element with the greatest quantity of units sold therefore has a count of zero. The plus method then adds 1 to each count amount so that the rank values begin with the number 1.

The join method of the Source produced by the plus method selects the elements of pcParentsAndChildren from all of the elements of the product hierarchy. The joinHidden methods then match Source objects that specify selections of the dimensions that are the remaining inputs of the units measure to produce result1, which specifies the calculation of the rank of the selected product elements relative to all of the product elements for the customer, time, and channel values.

The methods that product result2 are the same except that the first join produces a Source that specifies the units elements only for the elements of pcParentsAndChildren. The select, gt, count, and plus methods operate on only those selected elements of the hierarchy. The result2 Source therefore specifies the calculation of the rank of the selected product elements relative to each other rather than relative to all product elements.

Example 7-13 Ranking Products by Units Sold

// First result:  PC products unit sales ranked relative to all products.
Source result1 = units.join(prodRollup,
                            dp.getEmptySource(),
                            Source.COMPARISON_RULE_REMOVE,
                            false)
                      .select(units.value().gt(units)).count().plus(1)
                      .join(pcParentsAndChildren)
                      .joinHidden(custSel)
                      .joinHidden(timeSel)
                      .joinHidden(chanSel);
 
// Second result:  PC products unit sales ranked relative to each other.
Source result2 = units.join(pcParentsAndChildren,
                            dp.getEmptySource(),
                            Source.COMPARISON_RULE_REMOVE,
                            false)
                      .select(units.value().gt(units)).count().plus(1)
                      .join(prodRollup)
                      .joinHidden(custSel)
                      .joinHidden(timeSel)
                      .joinHidden(chanSel);

A Cursor for the result1 Source has the following values, displayed in a table with column headings and formatting added. The left column has the product element value and the right column has the rank of that product compared to all product units sold.

Rank Compared To
Product Element              Total Products Sold
-------------------------    -------------------
 
PRODUCT_ROLLUP::FAMILY::5            16
PRODUCT_ROLLUP::FAMILY::4            21
PRODUCT_ROLLUP::ITEM::16             29
PRODUCT_ROLLUP::ITEM::17             31
PRODUCT_ROLLUP::ITEM::18             34
PRODUCT_ROLLUP::ITEM::13             35
PRODUCT_ROLLUP::ITEM::14             37
PRODUCT_ROLLUP::ITEM::15             39

A Cursor for the result2 Source has the following values, displayed in a table with column headings and formatting added. The left column has the product element value and the right column has the rank of that product compared to the other product family members.

Rank Compared To
Product Element                   Each Other
-------------------------      ----------------
PRODUCT_ROLLUP::FAMILY::5             1
PRODUCT_ROLLUP::FAMILY::4             2
PRODUCT_ROLLUP::ITEM::16              3
PRODUCT_ROLLUP::ITEM::17              4
PRODUCT_ROLLUP::ITEM::18              5
PRODUCT_ROLLUP::ITEM::13              6
PRODUCT_ROLLUP::ITEM::14              7
PRODUCT_ROLLUP::ITEM::15              8

7.3.6 Selecting Based on Time Series Operations

This section has two examples of using methods that operate on a series of time dimension elements. Example 7-14 uses the lag method of unitPrice, which is the Source for the UNIT_PRICE measure, to produce unitPriceLag4, which specifies, for each element of unitPrice, the element of unitPrice that is four time periods before it at the same time dimension level.

In the example, dp is the DataProvider. Its createListSource method creates measuresDim, which has the unitPrice and unitPriceLag4 Source objects as its element values. The extract method of measuresDim gets the values of the elements of measuresDim. The Source produced by the extract method has measuresDim as an extraction input. The first join method matches a Source, measuresDim, to the input of the Source produced by the extract method.

The unitPrice and unitPriceLag4 measures both have the PRODUCT and TIME dimensions as inputs. The second join method matches quarterLevel, which is a Source for the QUARTER level of the CALENDAR hierarchy of the TIME dimension, to the measure input for the TIME dimension, and makes it an output of the resulting Source.

The joinHidden method matches prodSel to the measure input for the PRODUCT dimension, and does not make prodSel an output of the resulting Source. The prodSel Source specifies the single hierarchy element PRODUCT_ROLLUP::FAMILY::5, which is Desktop PCs.

The lagResult Source specifies the aggregate unit prices for each quarter and the aggregate unit prices for the quarter four quarters earlier for the Desktop PC product family.

Example 7-14 Using the Lag Method

NumberSource unitPriceLag4 = unitPrice.lag(mdmTimeHier, 4);
Source measuresDim = dp.createListSource(new Source[] {unitPrice, 
                                                       unitPriceLag4});
 
Source lagResult = measuresDim.extract()
                              .join(measuresDim)
                              .join(quarterLevel)
                              .joinHidden(prodSel);

A Cursor for the lagResult Source has the following values, displayed in a table with column headings and formatting added. The left column has the quarter, the middle column has the total of the unit prices for the members of the Desktop PC family for that quarter, and the left column has the total of the unit prices for the quarter four quarters earlier. The first four values in the right column are NA because quarter 5, Q1-98, is the first quarter in the CALENDAR hierarchy. The table includes only the first eight quarters.

Unit Price  
Quarter                Unit Price  Four Quarters Before
---------------------  ----------  --------------------
CALENDAR::QUARTER::5    16125.24               NA
CALENDAR::QUARTER::6    16226.89               NA
CALENDAR::QUARTER::7    16039.61               NA
CALENDAR::QUARTER::8    15526.53               NA
CALENDAR::QUARTER::9    21553.14         16,125.24
CALENDAR::QUARTER::10   21034.61         162,26.89
CALENDAR::QUARTER::11   21135.51         16,039.61
CALENDAR::QUARTER::12   19600.98         15,526.53
...

Example 7-15 uses the same unitPrice, quarterLevel, and prodSel objects as Example 7-14, but it uses the unitPriceMovingTotal measure as the second element of measuresDim. The unitPriceMovingTotal Source is produced by the movingTotal method of unitPrice. That method provides mdmTimeHier, which is an MdmLevelHierarchy component of the TIME dimension, as its dimension parameter and the integers 0 and 3 as the starting and ending offset values.

The movingTotalResult Source specifies, for each quarter, the aggregate of the unit prices for the members of the Desktop PC family for that quarter and the total of that unit price plus the unit prices for the next three quarters.

Example 7-15 Using the movingTotal Method

NumberSource unitPriceMovingTotal = 
                            unitPrice.movingTotal(mdmTimeHier, 0, 3);
 
Source measuresDim = dp.createListSource(new Source[] 
                                                {unitPrice, 
                                                 unitPriceMovingTotal});
 
Source movingTotalResult = measuresDim.extract()
                                      .join(measuresDim)
                                      .join(quarterLevel)
                                      .joinHidden(prodSel);     

A Cursor for the movingTotalResult Source has the following values, displayed in a table with column headings and formatting added. The left column has the quarter, the middle column has the total of the unit prices for the members of the Desktop PC family for that quarter, and the left column has the total of the unit prices for that quarter and the next three quarters. The table includes only the first eight quarters.

Unit Price Moving Total 
Quarter                Unit Price  Current Plus Next Three Periods
--------------------   ----------  -------------------------------
CALENDAR::QUARTER::5    16,125.24          63,918.27
CALENDAR::QUARTER::6    16,226.89          69,346.17
CALENDAR::QUARTER::7    16,039.61          74,153.89
CALENDAR::QUARTER::8    15,526.53          79,249.79
CALENDAR::QUARTER::9    21,553.14          80,206.84
CALENDAR::QUARTER::10   21,034.61          80,206.84
CALENDAR::QUARTER::11   21,135.51          77,638.28
...

7.3.7 Selecting a Set of Elements Using Parameterized Source Objects

Example 7-16 uses NumberParameter objects to create parameterized Source objects. Those objects are the bottom and top parameters for the interval method of prodRollup. That method produces paramProdSelInterval, which is a Source that specifies the set of elements of prodRollup from the bottom to the top positions of the hierarchy.

The product elements specify the elements of the units measure that appear in the result Source. By changing the values of the Parameter objects, you can select a different set of units sold values using the same Cursor and without having to produce new Source and Cursor objects.

The example uses the following objects.

  • dp, which is the DataProvider for the session.

  • prodRollup, which is the Source for the PRODUCT_ROLLUP hierarchy of the PRODUCT dimension.

  • prodShortDescr, which is the Source for the short value description attribute of the PRODUCT dimension.

  • units, which is the Source for the UNITS measure of product units sold.

  • chanRollup, which is the Source for the CHANNEL_ROLLUP hierarchy of the CHANNEL dimension.

  • calendar, which is the Source for the CALENDAR hierarchy of the TIME dimension.

  • shipRollup, which is the Source for the SHIPMENTS_ROLLUP hierarchy of the CUSTOMER dimension.

  • context, which has methods that prepare and commit the current Transaction, that create a Cursor for a Source, that display text, and that display the values of the Cursor.

The join method of prodShortDescr gets the short value descriptions for the elements of paramProdSelInterval. The next four join methods match Source objects to the inputs of the units measure. The example creates a Cursor and displays the result set of the query. Next, the setPosition method of resultCursor sets the position of the Cursor back to its first element.

The setValue methods of the NumberParameter objects change the values of those objects, which changes the selection of product elements specified by the query. The example then displays the values of the Cursor again.

Example 7-16 Selecting a Range With NumberParameter Objects

NumberParameter startParam = new NumberParameter(dp, 1);
NumberParameter endParam = new NumberParameter(dp, 6);
 
NumberSource startParamSrc = dp.createParameterizedSource(startParam);
NumberSource endParamSrc = dp.createParameterizedSource(endParam);

Source paramProdSelInterval = prodRollup.interval(startParamSrc,
                                                endParamSrc);
Source paramProdSelIntervalShortDescr =
                                  prodShortDescr.join(paramProdSelInterval);
 
NumberSource result = (NumberSource)
                       units.join(chanRollup, "CHANNEL_ROLLUP::CHANNEL::4")
                            .join(calendar, "CALENDAR::YEAR::4")
                            .join(shipRollup, 
                                  "SHIPMENTS_ROLLUP::ALL_CUSTOMERS::1")
                            .join(paramProdSelIntervalShortDescr);
 
// Get the TransactionProvider and prepare and commit the 
// current transaction. These operations are not shown.
 
CursorManagerSpecification cMngrSpec = 
                        dp.createCursorManagerSpecification(results);
SpecifiedCursorManager  spCMngr = dp.createCursorManager(cMngrSpec);
Cursor resultCursor = spCMngr.createCursor();
 
context.displayCursor(resultCursor);
 
//Reset the Cursor position to 1;
resultCursor.setPosition(1);
 
// Change the value of the parameterized Source
startParam.setValue(7);
endParam.setValue(12);

// Display the results again.
context.displayCursor(resultsCursor);

The following table displays the values of resultCursor, with column headings and formatting added. The left column has the product hierarchy elements, the middle column has the short value description, and the right column has the quantity of units sold.

Product                          Description           Units Sold
-------------------------------- ---------------------- ----------
PRODUCT_ROLLUP::TOTAL_PRODUCT::1 Total Product            55,872
PRODUCT_ROLLUP::CLASS::2         Hardware                 21,301
PRODUCT_ROLLUP::FAMILY::4        Portable PCs              1,420
PRODUCT_ROLLUP::ITEM::13         Envoy Standard              550
PRODUCT_ROLLUP::ITEM::14         Envoy Executive             482
PRODUCT_ROLLUP::ITEM::15         Envoy Ambassador            388
 
PRODUCT_ROLLUP::FAMILY::5        Desktop PCs               2,982
PRODUCT_ROLLUP::ITEM::16         Sentinel Standard         1,092
PRODUCT_ROLLUP::ITEM::17         Sentinel Financial        1,015
PRODUCT_ROLLUP::ITEM::18         Sentinel Multimedia         875
PRODUCT_ROLLUP::FAMILY::8        Monitors                  1,505
PRODUCT_ROLLUP::ITEM::20         Monitor- 15 Super VGA     1,238