Using MDX to Render Distinct Counts
We now have a set of "answers"
that we can attempt to replicate in direct MDX. Let's initialize the MDX Sample Application, as a platform from which to
perform our practice exercises, taking the following steps:
1.
Start the MDX
Sample Application.
We are
initially greeted by the Connect dialog, shown in Illustration 14.
The
illustration above depicts the name of my server, MOTHER1, and properly
indicates that we will be connecting via the MSOLAP provider (the
default).
The MDX
Sample Application window appears.
A
blank Query pane appears.
4.
Ensure that FoodMart
2000 is selected as the database name in the DB box of the toolbar.
5.
Select the Warehouse
cube in the Cube drop-down list box.
The MDX
Sample Application window should resemble that depicted in Illustration 15,
complete with the information from the Warehouse cube displaying in the Metadata
tree (left section of the Metadata pane).
Illustration 15: The MDX Sample Application Window
(Compressed View)
We
will begin creating our query, with a focus on returning results in the same
general formation as the Data View we left in the Cube Editor.
We will retrieve the Warehouse Profit and Product Count measures,
as pictured in Illustration 13 above. Next, we will attempt to add a
calculated measure that we craft directly in MDX, to replicate the distinct
count information we obtained with the Product Count measure that we
created in Analysis Manager earlier.
1.
Create the
following new query:
-- MXAS14- 1 Initial Attempt at Distinction
WITH MEMBER
[MEASURES].[ProdCount]
AS
'DISTINCTCOUNT({[Product].MEMBERS})'
SELECT
{ [MEASURES].[Warehouse Profit], [MEASURES].[Product Count],
[MEASURES].[ProdCount] } ON COLUMNS,
{[Product].CHILDREN} ON ROWS
FROM
[Warehouse]
The above represents an
attempt to meet the information consumers' objectives with what appears to be
the straightforward use of the DISTINCTCOUNT() function. This might
represent an approach that seems intuitive to a practitioner who has given up
on the handful of non-working or nebulous examples that can be found on the
web, (and which happen to be about all we seem to have as a basis for learning
MDX, in many instances). While it ultimately fails to provide the desired
solution, as we shall see, it should not be surprising that we might attempt
this, given the definition in the Books Online, not to mention the words
used in the name of the function itself. (Most will agree, also, that it is
better to attempt it now, than when under the gun of an employer or a hurried
client.)
The calculated member ProdCount
embodies the function. I named it ProdCount to distinguish if from Product
Count, the measure we created while within the user interface in the
earlier section, which I have also decided to present within the results
dataset for comparison purposes. Warehouse Profit is also presented to
align with our Data View as we left it in the last section.
2.
Execute the
query using the Run Query button.
The
results dataset appears as shown in Illustration 16.
Illustration 16: The
Results Dataset - DISTINCTCOUNT() Approach
3.
Save the query
as MXAS14-1.
It does not require a huge leap of logic to conclude that the ProdCount
calculated measure is generating a transaction count, which is probably
correctly "distinct," within its own (actual) meaning, but not at all
what the information consumers have requested in our practice example.
Bruised and humiliated (albeit briefly), let's resort to another,
more cumbersome approach, whose issue is at least the distinct product values.
4.
Create the
following new query:
-- MXAS14- 2 Distinction at its Finest
WITH MEMBER
[MEASURES].[CalcCount]
AS
'COUNT(CROSSJOIN({[MEASURES].[Warehouse Profit]}, DESCENDANTS
([Product].CURRENTMEMBER, [Product].[Product Name])), EXCLUDEEMPTY)'
SELECT
{[MEASURES]. [Warehouse Profit], [MEASURES].[Product Count], [MEASURES].[CalcCount] }
ON COLUMNS,
[Product].CHILDREN ON ROWS
FROM
[Warehouse]
The next attempt at
distinction is embodied by the calculated measure CalcCount, named,
again, simply as a means of distinguishing it from the measure we created in
the Cube Editor and which we include once again for comparison purposes.
The above approach may
not have been the initial impulse that many of us had in tackling what seemed
to be a straightforward replication of the Data View we saw earlier.
What we are doing, in short, with the CrossJoin() function is marrying
the Warehouse Profit values with the products, and returning
(thanks to EXCLUDEEMPTY) a count of the non-empty pairings.
The Descendants() function builds in flexibility, allowing us to apply
the logic equally well to a group of products as to the full set of products.
The key to this is the selection of the current member's descendents,
adding the "relativity" that so pointedly underscores the power of
the .CurrentMember function.
5.
Execute the
query using the Run Query button.
The
results dataset appears as shown in Illustration 17.
Illustration 17:
The Results Dataset - Distinction Attained
6.
Save the query
as MXAS14-2.
The values for the new measure are in alignment with those of the
measure we created in the Cube Editor.
NOTE: For a detailed introduction to most of the above
functions, see the Database Journal MDX Essentials Series
index page.
7.
Exit the MDX
Sample Application and Analysis Manager when ready.
Summary and Conclusion ...
In
this lesson, we introduced the concept of distinct counts, discussing
why they are often a requirement in our analysis efforts and those of the
information consumers whom we support. In our introduction, and throughout our
examination of the MDX syntax we explored to achieve our illustrative ends, we
highlighted the challenges that are inherent in distinct counts. We
performed practice exercises, to illustrate solutions for hypothetical business
needs that called upon the use of distinct count capability, obtaining
exposure to the options afforded us by the MSAS user interface, as well the MDX
syntax involved with using the alternative solutions that we proposed.
In
future articles, we will examine the performance considerations inherent in the
production of distinct counts, as well as options
that are available to tune our efforts for more efficient operation. The need
for distinct counts is a fact of business life, and mastery of the costs
and results of this vital capability represent a unique opportunity to add
another tool to our MSAS skill sets.
»
See All Articles by Columnist William E. Pearson, III