Try again

200512270453934121.gif

博客园 首页 联系 管理

Title: MDX(1)
Publisher: Friend Lv


 

Lab 1: Introduction to MDX

 

 

 

 

 

 

Lesson 1: MDX and the Sample Application

Lesson 2: Basic MDX Syntax

 

 

 

 

 

 

 


 


This page left intentionally blank

Lesson 1: MDX and the Sample Application

This lesson will define MDX and learn its uses. Then it will discuss and create a simple query using the MDX sample application.

What You Will Learn

After completing this lesson, you will be able to:

·         Define MDX

·         List the MDX terms and the analogous terms in SQL

·         Use the MDX Sample Application

·         Describer the data structures in the FoodMart database

·         Write a simple MDX statement

 

Before You Begin

Prerequisites

·         Those who are familiar with the SQL language or an equivalent database language will have an advantage when learning MDX.

Lab Setup

·         You must have a workstation with SQL Server OLAP services installed. The OLAP installation will setup the FoodMart database, which is used throughout this Lab.

 


MDX Defined

What is MDX?

The name MDX originated from Multi-Dimensional eXtensions. As this origin implies, MDX started as extensions to the SQL language.  If you know the SQL language, you will have a good platform for learning MDX. But don’t be led to believe that it is SQL with a bit extra, it has a very different structure from SQL.

Is MDX like SQL?

Very simple MDX statements resemble SQL, they both take the format

 SELECT …..
 FROM ….
 WHERE ….

That is where the similarity ends. However someone with SQL skills will have a good base for learning MDX. Both are data manipulation languages.

Why MDX, why not SQL?

MDX is designed to facilitate queries on multidimensional cubes, while the SQL language is designed to facilitate queries on two-dimensional tables.

SQL and MDX Analogous Terms

Multidimensional Term

Relational Analog

Cube

Table

Level

Column (string or discrete numeric)

Dimension

Several related columns or dimension table

Measure

Column (discrete or continuos numeric)

Dimension member

The value in the specific row and column corresponding to the given dimension level

 

How does OLE DB fit in?

OLE DB is a data access API. Just as you can call relational database OLE DB providers with SQL requests, you can call OLAP OLE DB providers with MDX queries.

 


The MDX Sample Application

The MDX Sample application started out in life, as its name implies, a sample application to demonstrate how to call OLAP from a VB application. This application was the only interface that supported freeform MDX. Subsequently its importance rose. It is currently not an official part of SQL Server 7.0, but being the only MDX query editor it is extremely useful. Being a sample application, you get the source code for the MDX Sample with SQL Server. By default the sample application will be found at C:\Program Files\OLAP Services\Samples\MdxSample\. This is what the application looks like:


Notice that it has 4 panes. The top pane is where you can type in your MDX query; the bottom pane is where the results are displayed; the middle left pane is displaying the cube structure; and the middle right pane contains templates for MDX functions. This application is very useful in the way it supports drag and drop from the cube structure and function templates to the query pane.

 


The Sample Database

All examples in this lab are based on the Sales cube in the FoodMart sample database. This cube has been designed to facilitate the analysis of a chain of grocery stores and their promotions, customers and products. We have the following dimensions:

Sales Cube Dimensions

Key Points

Take a moment to review this information about the data cube.

- In particular note that some dimensions such as Customers have several levels.

- Some dimensions such as Gender and Marital Status have only one level.

Dimension Name

Level

Description

Customers

Country, State or Province, City, Name

Geographical hierarchy for registered customers of our stores

Education Level

Education Level

Education level of customer, such as “Graduate Degree”, “High School Degree”

Gender

Gender

Customer gender, “M” or “F”

Marital Status

Marital Status

Customer marital status “S” or “M”

Product

Product Family, Product Department, Product Category, Product Subcategory, Brand Name, Product Name

The products that are on sale in these stores.

Promotion Media

Media Type

The media used for a promotion, such as Daily Paper, Radio, etc.

Promotions

Promotion Name

Identifies promotion that triggered the sale

 Store

Store Country, Store State, Store City, Store Name

Geographical hierarchy for different stores in the chain (country, state, city)

Store Size in SQFT

Store Sqft

Area occupied by store, in square feet.

Store Type

Store Type

Type of store, such as “Deluxe Supermarket”, “Small Grocery” etc

Time

Years, Quarters, Months

Time period the sale was made

Yearly Income

Yearly Income

Income of customer

Notice how some Dimensions, such as Customers, have multiple levels. This means that the dimension is hierarchical. Country is the highest level, each country will have one or more State Provinces; each State Province will have one or more cities; and each city will have one or more Names (customers).


Sales Cube Measures

Measure Name

Description

Unit Sales

Number of units sold

Store Cost

Cost of goods sold

Store Sales

Value of Sales transactions

Sales Count

Number of Sales transactions

Store Sales Net

Value of Sales transactions less cost of goods sold

Average Sale

“Store Sales”/”Sale Count”.  This is a Calculated Measure, which means that it is derived from other measures and does not need to be stored in the cube.

Measures are the things you want to aggregate (count, sum, average, max, min etc.) When you come to writing MDX, it is useful to think of measures as like dimensions. In MDX whenever we reference a cell, we explicitly or implicitly specify which member of every dimension and measure we want as coordinates for that cell.


Basic MDX

Let’s think about our first MDX query. The simplest MDX query has the following structure:

SELECT something ON COLUMNS
FROM cube

So far MDX syntax looks similar to SQL. This is where the similarity ends. MDX is a language designed for multidimensional cubes. Dimensions are the basic constructs, not tables.

In MDX, we can specify any number of dimensions in our resultset. We will call them axes to prevent the confusion with a cube’s dimensions. We can have zero, one, two, three…n. axes.  All of the axes are symmetric. That means, whatever we can do on one, we can do on another. Typically MDX queries don’t have more than two dimensions in the resultset as we do not have many tools to display more than two-dimensional results.

Members

A member is an item in a dimension or measure[1]. For example in the Gender dimension “M”, “F” and “All Gender” are all members.


Exercise 1
Using the MDX Sample Application to Write a Simple MDX Query

In this exercise, you will open the MDX sample program, create and execute a simple query.

Opening the MDX Sample Application

Let’s start the MDX Query Application.

1.        From the Start menu select Programs, Microsoft SQL Server 7.0, OLAP Services, and the MDX Sample Application.

2.        You will be prompted for the server and the provider. Enter the name of the server that has the OLAP Services and sample database installed. By default it is the Windows NT name of your machine. Leave the provider as MSOLAP and select OK. The MDX Sample Application will start.

3.        Select the “FoodMart” database from the “DB” drop down list at the top of the screen.

4.        Select the “Sales” cube from the “Cube” drop down list near the middle of the screen.

5.        Select New from the File menu (or click on the “New Query File” button at the left of the toolbar).

We now have a fresh query window to start MDXing.

Your first MDX query

Your first MDX query will report on the number of units sold to male versus female customers.

1.        Type the following query into the new query window.

SELECT
   Gender.MEMBERS ON COLUMNS
FROM Sales

2.        Run the query by clicking the green arrow on the toolbar (or click the F5 key).

Note

Notice, how the result set also has a column headed “All Gender.” By default, MS OLAP will create an “All” level at the peak of the hierarchy. When you create dimensions in Plato, the “All” member is generated by default and it becomes the default member. This turns out to be very useful. In our query, we did not specify which member of the “Marital Status” dimension to use, so Plato used the default member “All”. By default this member has the format [All dimensionname], but if the dimension name is very large, it might be abbreviated to [All].  You may call the all member by any name. For example in the FoodMart database the all member of “Media Type” is “All Media”.

Now that you are familiar with the MDX Sample Application proceed to lesson 2 to study MDX syntax.

 


 


Lesson 2: Basic MDX Syntax

Now the fun starts:

We are now going to write some MDX queries. In some ways MDX is simpler than SQL.  Plato has a lot of meta knowledge. That is, it knows about the relationships between the dimensions and members. You do not need to write INNER, LEFT/RIGHT/FULL OUTER JOIN etc.

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 Queries

Now we will explore some additional concepts.

Two Dimensional Queries

MDX 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
Gender.MEMBERS ON COLUMNS,
Measures.MEMBERS ON ROWS
FROM Sales

Congratulations, you have written a two dimensional query.

Identifiers and Qualifiers

In the MDX language, identifiers can be delimited with square brackets.

2.        Update the above query to use delimiters around the member names.

SELECT
[Gender].MEMBERS ON COLUMNS,
[Measures].MEMBERS ON ROWS
FROM Sales

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
[Marital Status].MEMBERS ON COLUMNS,
[Promotion Media].MEMBERS ON ROWS
FROM Sales

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
{[Marital Status].MEMBERS} ON COLUMNS,
{[Promotion Media].MEMBERS} ON ROWS
FROM Sales

 

Children

For Your Information

Remember the chart on page 6. - The Customers dimension had several levels.

- Marital Status had only one level.

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
{[Marital Status].MEMBERS} ON COLUMNS,
{[Customers].CHILDREN} ON ROWS
FROM Sales

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
{[Marital Status].MEMBERS} ON COLUMNS,
{[Customers].[USA].CHILDREN} ON ROWS
FROM Sales

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
{[Marital Status].MEMBERS} ON COLUMNS,
{[Customers].[USA].[WA].CHILDREN} ON ROWS
FROM Sales

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 Clause

At 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
{[Education Level].MEMBERS} ON COLUMNS,
{[Marital Status].CHILDREN} ON ROWS
FROM Sales
WHERE Gender.[M]

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
{[Education Level].MEMBERS} ON COLUMNS,
{[Marital Status].CHILDREN} ON ROWS
FROM Sales
WHERE (Gender.[M],[Promotion Media].[Radio])

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],
[Promotion Media].[All Media].[Radio])

 [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 measure

What 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
{[Education Level].MEMBERS} ON COLUMNS,
{[Marital Status].CHILDREN} ON ROWS
FROM Sales
WHERE (Gender.[M],[Promotion Media].[Radio],
Measures.[Store Sales])

 

 

 

 

 

 

Review of Brackets, Braces and Parentheses

Let’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 Basics

Now 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
Measures.MEMBERS ON COLUMNS,
[Promotion Media].MEMBERS ON ROWS
FROM Sales

2.        Suggested syntax:

SELECT
Product.CHILDREN ON COLUMNS,
[Gender].MEMBERS ON ROWS
FROM Sales

3.        Suggested syntax:

SELECT
[Product].[Drink].CHILDREN ON COLUMNS,
[Marital Status].MEMBERS ON ROWS
FROM Sales
WHERE [Gender].[F]

This query shows figures for [Unit Sale] as it is the default measure.

4.        Suggested syntax:

SELECT
Product.CHILDREN ON COLUMNS,
[Marital Status].MEMBERS ON ROWS
FROM Sales
WHERE ([Gender].[F], Measures.[Store Sales Net])


Axes and Members

Enumerating 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
{[Time].[1997].CHILDREN} ON COLUMNS,
{Promotions.[All Promotions].[Price Destroyers],
   Promotions.[All Promotions].[Price Slashers],
   Promotions.[All Promotions]} ON ROWS
FROM Sales

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
{[Time].[1997].CHILDREN} ON COLUMNS,
{[Price Destroyers], [Price Slashers],
   [All Promotions]} ON ROWS
FROM Sales

 

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
{[Time].[1997].[Q1].[1],
 [Time].[1997].[Q1].[2],
 [Time].[1997].[Q1].[3],
 [Time].[1997].[Q2].[4]} ON COLUMNS,
{[Price Destroyers],
 [Price Slashers],
 [All Promotions]} ON ROWS
FROM Sales
WHERE (Gender.[M],
Customers.[USA].[WA],
Measures.[Store Sales])

 

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
{[Time].[1997].CHILDREN} ON COLUMNS,
{([Customers].[USA].[WA], [Gender].[F]),
 ([Customers].[USA].[CA], [Gender].[M])} ON ROWS
FROM Sales
WHERE (Measures.[Store Sales])

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.

 

Review

Finally, 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
{[Customers].[All Customers].[USA].CHILDREN}
  ON COLUMNS,
{([Gender].[M],[Marital Status].[S]),
 ([Gender].[M],[Marital Status].[M]),
 ([Gender].[F],[Marital Status].[S]),
 ([Gender].[F],[Marital Status].[M])} ON ROWS
FROM Sales
WHERE ([Store Sales])


The Use of Functions

At 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
{[Customers].[All Customers].[USA].CHILDREN}
  ON COLUMNS,
{CROSSJOIN([Gender].CHILDREN,
  [Marital Status].CHILDREN)} ON ROWS
FROM Sales
WHERE ([Store Sales])

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
{[Customers].[All Customers].[USA].CHILDREN}
  ON COLUMNS,
{CROSSJOIN([Gender].MEMBERS,
  [Marital Status]. MEMBERS)} ON ROWS
FROM Sales
WHERE ([Store Sales])

 

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.

 


 



[1] It is often useful to view measures as a dimension, albeit a special one.

[2] Ignoring any politically correct debate

posted on 2005-05-30 11:20  共同学习,共同进步  阅读(567)  评论(0编辑  收藏  举报