What You Will Learn
After completing this lesson, you will be able to:
· Write two dimensional MDX statements
· Use identifiers
· Use the CHILDREN syntax
· Apply a WHERE clause
· Enumerate the axes
Making More Complex QueriesNow we will explore some additional concepts. Two Dimensional QueriesMDX can request resultsets with more than two dimensions. However, most tools have difficulty in presenting more than two dimensions. Hence, two-dimensional queries are the most common. Lets enhance the previous query by putting measures on rows.
1. Add a comma after COLUMNS and insert a new line with “Measures.MEMBERS ON ROWS”. SELECT Congratulations, you have written a two dimensional query.
Identifiers and QualifiersIn the MDX language, identifiers can be delimited with square brackets.
2. Update the above query to use delimiters around the member names. SELECT Square brackets are always required when identifiers have spaces, are numbers or are also reserved words. MEMBERS is a reserved word, hence you should not enclose it in square brackets (unless you have a member called “MEMBERS”). Now that we know how to qualify identifiers we can query on any of the dimensions.
3. Update your query to report [Marital Status].MEMBERS ON COLUMNS and [Promotion Media].MEMBERS ON ROWS. SELECT Set Identifiers
Curly brackets are used to denote sets. [Marital Status].MEMBERS and [Promotion Media].MEMBERS are sets and can be delimited by curly brackets. In the preceding query, Plato “knew” they were sets so the curly brackets were not necessary. However sets are not always evident to Plato. Hence it is good practice to write queries with curly braces.
4. Put curly braces around the set specifications in your query. SELECT
Children
Dimensions are often hierarchical. For example, our Customers dimension has 4 levels (Country, State or Province, City, Name). If we write a query using Customers.members on one of the axes, we are asking for the items at every level of the Customers dimension. That is all Countries, all States/Provinces, all Cities, and all Names. Perhaps we only want the members at one level. Children are very useful in limiting the output to the immediate level. For example, let’s report on the Customers dimension at the first (country) level.
5. Write a query that has [Marital Status].MEMBERS on columns and [Customers].CHILDREN on rows. SELECT Note Notice how the resultset only includes members of the first level of Customers. That is Country. Expand the Customers dimension on the cube browser pane (middle left) to view the levels in the Customers dimension. You might also notice in the results that we only have figures for USA. While Canada and Mexico are valid countries, there is no data to report on. You might say, that there could be stores in Canada and Mexico, but as yet there are no Sales.
We might want to drill down on USA and show the figures for states within the USA.
6. Use the CHILDREN keyword on the [Customers].[USA] member to show the USA states. SELECT This query asks for all the children members (all states) within USA. Notice how Plato knows about this hierarchy. We did not have to specify parent child joins as we would normally need to in SQL. We could further drill down on one of the states.
7. Ask for all the cities in WA by typing “.[WA]” after “[USA]” in your query. SELECT Note You can pivot the result set with a button on the far right of the toolbar. Look for the curved double-headed arrow. The WHERE ClauseAt first glance the WHERE clause appears similar to the corresponding clause in SQL. For example, we might want to report on Education Level by Marital Status, but only where customers are male.
8. Update your query by inserting a line at the end and type “WHERE Gender.[M]” SELECT If we want to add further filters to the WHERE clause we enclose the whole WHERE clause in rounded brackets and dimension filters with commas. For example we might want to restrict the previous query to only those Sales where the sale was induced by a promotion media of “Radio”.
9. Add “,[Promotion Media].[Radio]” to the end of your WHERE clause and enclose the clause in rounded brackets. SELECT We could continue to add filters to the WHERE clause, until we had one for each dimension. But we cannot create a query with a dimension on an axis (row or column) and in the WHERE clause. For example in the previous query, it would be illegal to put [Education Level].[Graduate Degree] on the where clause.
[Gender] and [Promotion Media] dimensions both have (the default) all level. Hence if we were to be particular about writing the WHERE clause we would have written it as:
WHERE (Gender.[All Gender].[M], [M] and [Radio] are not ambiguous in their respective dimensions, so it was not necessary to qualify them with their parent level. Indeed if the member is unambiguous in the cube, it is not necessary to qualify it at all. However, it is a good practice to qualify members.
There are many dimensions not specified in this query. For non-specified dimensions, it is useful to think of them as being specified with their default member, which is usually the [All] member.
The full measureWhat if we want to measure something other than [Unit Sales]? The preceding queries have reported on the default measure (Unit Sales). It is the default measure because there is no [All] member and [Unit Sales] is the first member of Measures. If we want to report on another dimension, we would name it in the WHERE clause.
10. Modify the preceding query to report on Store Sales instead of Unit Sales by adding “,Measures.[Store Sales]” to your WHERE clause. SELECT
Review of Brackets, Braces and ParenthesesLet’s recap this area, as it is often an area of confusion.
· Square brackets [ ] are used to delimit member names. · Curly brackets { } are used to define sets. · Round brackets ( ) are used in functions and to delimit tuples. There will be examples of these soon. Note A tuple is another word for a row in a table.
Review - Practicing the BasicsNow you know the basics of the MDX query language. Let’s practice using these elements before we move onto more sophisticated aspects of the language. The answers are at the bottom of the page. All examples use the Sales cube.
1. Write a query to show measures on columns and all of the [Promotion Media] members on rows. 2. Write a query to show the first level members (CHILDREN) of Product on columns and gender members on rows. 3. Write a query to show the first level members (CHILDREN) of [Product].[Drink] on columns and [Marital Status] members on rows. But only show figures for Gender [F]. 4. Modify the WHERE clause so the report shows [Store Sales Net] figures.
Answers:1. Suggested syntax:
SELECT 2. Suggested syntax:
SELECT 3. Suggested syntax:
SELECT This query shows figures for [Unit Sale] as it is the default measure.
4. Suggested syntax:
SELECT Axes and MembersEnumerating Our Own Axes
So far we have only used the MEMBERS and CHILDREN collections of dimensions. Very often we want to be more precise than this. We might want to report on just two selected products, or we might want to select months October and November and the full year. Fortunately, in MDX we can specify exactly which members we want on an axis. We do this by enumerating our own set with declared tuples. For example, there are lots of promotions, but we only want to look at [Price Destroyers], [Price Slashers], and [All Promotions].
1. Enclose the above promotions within curly braces, which delimit the set, to enumerate your own row axis. Put {[Time].[1997].CHILDREN} on columns. SELECT Note We have written the fully qualified member names with all levels qualified. Because the low level member names are not ambiguous, an equivalent query would be:
SELECT
We can combine these enumerated axes with a WHERE clause and our query starts to get interesting.
2. Write a query to look at January, February, March and April of 1997 on columns, [Price Destroyers], [Price Slashers], [All Promotions] on rows, and filter for store Sales to male customers in the state [WA]. And we want to measure [Store Sales]. SELECT
Let’s create our own tuples for the axis
In the previous section we enumerated our own axes from individual members. We can take that further by specifying dimension intersections on axes. For example[2] we might want to compare Store Sales to female customers in WA compared with male customers in CA. And view this by quarters of the year 1997. The tuple females in WA can be specified as ([Customers].[USA].[WA],[Gender].[F]), likewise males in CA can be specified as ([Customers].[USA].[CA],[Gender].[M]).
3. Put these together to make a request to show [Store Sales] with 1997 quarters on columns, Female WA customers on one row and male CA customers on another row. SELECT All members welcome
Whenever we specify a tuple, we are actually specifying an intersection of all dimensions. The dimensions that we do not specify have their default member included. You might see now why it is useful to have the [All] member as the default member.
Note There is no [All] member for measures. It does not make sense to aggregate the different measures. For measures, the default member is the first member. Some of your cubes may have dimensions without an [All] level. For example, Time dimensions often do not have [All] levels. Also a dimension with members [Forecast] and [Actual] might not have an [All] member. A default of either [Forecast] or [Actual] is probably more useful.
ReviewFinally, let’s do an exercise to review the previous sections.
1. Write a query to report on store Sales; put the USA states on columns and all the combinations of gender and marital status on rows. Answer:SELECT The Use of FunctionsAt this stage you would be forgiven for thinking that MDX would be difficult for complex reports. Fortunately, it has the richness of many functions. We will introduce one here in our discussion of syntax.
The CROSSJOIN Function
As we said, MDX, like SQL, is a redundant language. That is, the same request, can be written in many different (redundant) ways. The previous query, for example, wanted all the possible join combinations between [gender] and [marital status] on rows. We wrote the MDX with the members hard coded. How about just asking Plato to join all the possible combinations using the CrossJoin function such as:
SELECT Of course if we wanted to have totals by [gender] and [marital status] we could use MEMBERS in place of CHILDREN.
2. Modify the previous query to use Members for both gender and marital status. Warning Note: Using members for the customers dimension might not be such a good idea as that would involve loading all 10,000 customers in the MDX Sample Application. SELECT Congratulations
You have completed this Introduction to MDX. You should now know what MDX is and how to use the language to write basic queries. If you would like to continue to learn more about the richness of this language, go on to Lab 2: MDX Functions and Calculated Members.
|