# MDX Numeric Functions: The Min() Function

Monday Feb 4th 2008 by William Pearson

Business Intelligence Architect Bill Pearson introduces the numeric Min() function, and leads hands-on practice examples of its use.

This article is a member of the series, MDX Essentials. The series is designed to provide hands-on application of the fundamentals of the Multidimensional Expressions (MDX) language, with each tutorial progressively adding features designed to meet specific real-world needs.

For more information about the series in general, as well as the software and systems requirements for getting the most out of the lessons included, please see my first article, MDX at First Glance: Introduction to MDX Essentials.

Note: Current updates are assumed for MSSQL Server, MSSQL Server Analysis Services, and the related Books Online and Samples.

### Overview

In this article, we will introduce another “staple” MDX numeric function, the Min() function. Min(), like Max(), is one of several aggregate functions with which we can choose to perform aggregations upon a set of values. (We introduce other aggregate functions within individual articles of the MDX Essentials series.) Min(), like the rest of these functions, aggregates a set of (one or more) measure values associated with a set of dimension members. Simple examples might include the selection of the minimum revenue from a set of products or the minimum monthly personnel headcount over a range of months.

As many of us are already aware, Min() can be leveraged throughout a wide range of activities, from the generation of minimums from simple sets of dimensional members to the composition of multidimensional juxtapositions, for more sophisticated results. As is the case with many MDX functions, Min() can serve as an excellent tool to support sophisticated conditional logic, as well as other calculations, and to deliver exactly the analysis and reporting presentations required by our clients and employers. We will introduce the function, commenting upon its operation and touching upon creative effects that we can employ it to deliver. As a part of our discussion, we will:

• Examine the syntax surrounding the function;
• Undertake illustrative examples of the uses of the function in practice exercises;
• Briefly discuss the results datasets we obtain in the practice examples.

### The Min() Function

#### Introduction

According to the Analysis Services Books Online, the Min() function “returns the minimum value of a numeric expression that is evaluated over a set.” Min() has myriad applications, ranging from those that are obvious and intuitive to even the most inexperienced MDX users, to others that offer sophisticated solutions for more elaborate business requirements, such as the selection of transaction or balance values as of the “earliest” date, in combination with other dimensional components, within our cubes. The function can be leveraged within queries to create datasets, in reporting applications such as MSSQL Server Reporting Services, for the support of presentations of simple minimums, for the support of intelligent default dates within our report parameters, and a host of other creative and useful effects. The Min() function provides an intuitive option anytime we need to present, in a returned dataset, the smallest / lowest value(s), based upon a numeric expression and a set we supply. As is the case with most MDX functions, combining Min() with other functions allows us to further extend its power, as we shall see in the practice exercises that follow.

We will examine the syntax for the Min() function after a brief discussion in the next section. We will then explore, from the straightforward context of MDX queries, and within practice examples constructed to support hypothetical business needs, some of the utility it offers the knowledgeable user. This will allow us to activate what we learn in the Discussion and Syntax sections, and allow us to get some hands-on exposure in creating expressions that employ the Min() function.

#### Discussion

To restate our initial explanation of its operation, the Min() function returns the minimum value of a numeric expression we supply, for the members of a set which we also specify. Min() can be used for a great deal more than simple “minimum value” retrieval, as we have intimated. When we couple it with other functions or employ it within MDX scripts, among other applications, we can leverage Min() to support a wide range of analysis and reporting utility.

Let’s look at some syntax illustrations to further clarify the operation of Min().

#### Syntax

Syntactically, we employ the Min() function by specifying a Set Expression (a valid MDX expression that returns the set over which we are attempting to return an associated “minimum” value), followed by a Numeric Expression (a valid numeric expression that is typically an MDX expression of cell coordinates that returns a number) within parentheses to the immediate right of the function. The function takes the Set Expression and Numeric Expression thus appended as its arguments (the two expressions are separated by a comma), and evaluates the Numeric Expression across the set. The minimum value from that evaluation is returned. (If a Numeric Expression is not specified, the set specified by the Set Expression is evaluated in the current context of the members of the set, and the minimum value for the evaluation is returned.) Analysis Services ignores nulls when calculating the minimum value within a set of numbers. Because Min() returns a numeric value, we use it most commonly within the construction of calculated members.

The general syntax is shown in the following string:

` Min(Set_Expression, Numeric_Expression)`

Putting Min() to work is straightforward. When using the function to return the minimum value(s) of the Numeric Expression we have provided as evaluated over the set we have specified, we simply supply the required Set and Numeric Expressions within the parentheses to the right of the Min keyword. As an example, say we create, within a query executed against the sample Adventure Works cube, a calculated member which we might name “Bottom Orders,” (that is, say, for the “lowest value for the Internet Order Count measure”) containing the following pseudo code:

```MIN( [Date].[Calendar Year].[CY 2001]:[Date].[Calendar Year].[CY 2004],
[Measures].[Internet Order Count] )```

Moreover, say that we select the set of the same Date range dimensional members and the calculated member within our column axis, and the Product Category members within our row axis, we might expect to retrieve results similar to those depicted in Illustration 1.

Illustration 1: Example Returned Data: Min() Function Employed in Calculated Member

It is easy to see, within the dataset returned above, that the minimum value, based upon the members of the dimensional date range we have provided, is returned, as the calculated member value presents the lowest value within each of the rows retrieved. Because of the ease with which we can employ Min(), and because of the flexibility with which we can exploit it to meet various business needs, the function becomes a popular member of our analysis and reporting toolsets. We will practice some uses of the Min() function in the section that follows.

#### Practice

Preparation: Access SQL Server Management Studio

To reinforce our understanding of the basics we have covered, we will use the Min() function within queries that illustrate its operation. The intent is to demonstrate the use of Min() in a straightforward, memorable manner that efficiently illustrates its operation.

We will turn to the SQL Server Management Studio as a platform from which to construct and execute the MDX we examine, and to view the results datasets we obtain. If you do not know how to access the SQL Server Management Studio in preparation for using it to query an Analysis Services cube (we will be using the sample Adventure Works cube in the Adventure Works DW Analysis Services database), please perform the steps of the following procedure, located in the References section of my articles index:

This procedure will take us through opening a new Query pane, upon which we will create our first query within the section that follows.

Procedure: Satisfy Business Requirements with MDX

Let’s construct a simple query to provide a conceptual “starting point” for illustrating the use of the Min() function. The idea is to generate a basic dataset that shows the concepts behind using the Min() function and to introduce some of the ways we can employ it effectively. Once we have accomplished our immediate goal in our first practice example, we will further evolve these concepts in meeting another business requirement in the procedure that follows it.

Procedure: Use the Min() Function to Generate a Simple “Minimum Value” in a Results Dataset

Let’s say that information consumers from the Adventure Works Logistics department, whose data is housed within the Adventure Works cube, come to us with a straightforward request: The consumers wish to see the bottom Internet Sales Amounts, based upon the organization’s Sales Territory Countries, for each of the Product Category groups offered by Adventure Works to its customers. They prefer to present the totals (leaving out nulls) for the member Product Categories sold by each Country, along with the lowest values among those Country totals (in a column called “Bottom Sales”), on each row of the returned data set.

The basic Min() function involved will be housed within a calculated member we will call Bottom Sales. We will then employ the calculated member within a core query that presents the information in the manner requested. Our query will be constructed as described in the following procedure.

1.  Type (or cut and paste) the following query into the Query pane:

```
-- MDX063-1: Basic Use of MIN() Function
WITH
MEMBER
[Sales Territory].[Sales Territory].[Bottom Sales]
AS
'MIN(  { [Sales Territory].[Sales Territory].[Country].MEMBERS},
[Measures].[Internet Sales Amount])'
SELECT
{ [Sales Territory].[Sales Territory].[Country].MEMBERS,
[Sales Territory].[Bottom Sales]  } ON AXIS(0),
NON EMPTY   {[Product].[Product Categories].[Category].MEMBERS} ON AXIS(1)
FROM
WHERE
([Measures].[Internet Sales Amount])
```

Our query is simply expressing that we wish to retrieve the “total value of Internet Sales,” for each of our general Product Categories, by Sales Territory Country, alongside a repetition of the lowest value within each row, within a column we label “Bottom Sales.” We are ignoring time – the consumers are aware that the cube contains data from several years, and they want the information to be based upon the cube as a whole for their present purposes. Moreover, they realize that, once they use the scenario we have assembled to verify effective operation of the Min() function (inside the “Bottom Sales” calculation we have built), they may jettison the individual Sales Territory Country columns, at least in reports they create later, based upon our example. (Parameterization, in an application like Reporting Services, becomes an easy objective, of course.)

The Query pane appears, with our input, as shown in Illustration 2.

Illustration 2: Our Initial Query in the Query Pane ...

The above query demonstrates the basic use of Min(), and accomplishes the objective of illustrating, in the simplest manner, how it works. The idea is to generate a dataset to activate the concepts in the minds of our client colleagues.

2.  Execute the query by clicking the Execute button in the toolbar, as depicted in Illustration 3.

Illustration 3: Click Execute to Run the Query...

The Results pane is populated by Analysis Services, and the dataset, shown in Illustration 4, appears.

Illustration 4: Results Dataset – Simple “Minimum Value” Scenario

In the returned dataset, we see the members of the Country level of the Sales Territory dimension (Sales Territory hierarchy) appear upon the column axis, and the members of the Category level of the Product dimension (Product Categories hierarchy) appear upon the row axis. We have retrieved, for each intersection, the non-null Internet Sales Amount values, together with the value of the calculated member Bottom Sales that corresponds with each Product Category row. This simple dataset provides a great “beginner” illustration of the output of Min(), as we can see that the function generates the correct minimum value that appears in the respective Country column to its left.

NOTE: For more detail surrounding the .Members function, see my article MDX Members: Introducing Members and Member, a member of my MDX Essentials series at Database Journal.

3.  Select File -> Save MDXQuery1.mdx As ..., name the file MDX063-001, and place it in a meaningful location.

Our client colleagues express satisfaction with the contextual backdrop we have established for introducing the Min() function. We will employ the function again in our next steps to extend our understanding of its basic use.

Procedure: Use the Min() Function to Select Least Sales

Having demonstrated the basic operation of Min(), we are ready to address another requirement that the client representatives describe. To detail the requirement, our colleagues have asked us to address a specific, immediate need, although they hope to be able to extrapolate the concepts we introduce to other, similar needs that commonly arise within the organization. Our colleagues have asked that we construct a query that presents a dataset similar to the one we have described above, in that it uses the Min() function to retrieve a minimum measure value for a specified set.

As we have noted, of course, Min() can be used in numerous ways that lie beyond the obvious selection of the ”least number” or “smallest amount” for a set we specify as a basis in the function. We often, for instance, use the function to select the “first” (or “least”) month (or other Date period), as an example, where we have conducted transactions or maintained a balance.

Our colleagues tell us that they wish to support the capability of Logistics users to report upon and analyze “least” sales of the Resellers, with which Adventure Works maintains relationships, to market and distribute its products. To begin, they wish to be able to generate a dataset that presents the lowest monthly sales values for Resellers who have completed sales within Calendar Year 2003. The client representatives make us aware that they wish to screen out Resellers who have no activity at all over the given Calendar Year, simply to streamline reports and make them more compact.

We explain that the Min() function promises to be useful in generating the desired presentation. We confirm our understanding of the foregoing requirement, as well as our conclusion that we have happened upon a great opportunity to both assist the client in meeting its immediate needs as well as to provide examples that leverage the MDX Min() function. We set out to craft a query that relies upon Min(), in conjunction with other MDX functions, to meet the business requirement.

The basic Min() function involved will be housed within a calculated member, which we will call Lowest Sales. We will then employ the calculated member within a core query that arranges the information it retrieves in the manner requested. Our query will be constructed as described in the following procedure.

1.  Select File --> New from the main menu.

2.  Select Query with Current Connection from the cascading menu that appears next, as depicted in Illustration 5.

Illustration 5: Create a New Query with the Current Connection ...

A new tab, with a connection to the Adventure Works cube (we can see it listed in the selector of the Metadata pane, once again) appears in the Query pane.

3.  Type (or cut and paste) the following query into the Query pane:

```
-- MDX063-2 Second Example of MIN() Function in Use
WITH
MEMBER
[Measures].[Lowest Sales]
AS
'MIN(DESCENDANTS( [Date].[Calendar].[Calendar Year].[CY 2003],
[Date].[Calendar].[Month]),
[Measures].[Reseller Sales Amount]
)'

SELECT
{[Measures].[Lowest Sales]} ON AXIS(0),
NON EMPTY
{[Reseller].[Reseller Type].[Reseller].MEMBERS}
ON AXIS(1)
FROM
```

The Query pane appears, with our input, as shown in Illustration 6.

Illustration 6: Our Second Query in the Query Pane ...

For those Resellers experiencing at least one sale within Calendar Year 2003, we derive a Lowest Sales value using the Min() function, specifying the members of the Month level of the Date dimension (Calendar hierarchy) as the Set Expression across which the Numeric Expression, representing the Reseller Sales Amount measure, is evaluated.

4.  Execute the query by clicking the Execute button in the toolbar.

The Results pane is, once again, populated by Analysis Services. This time, the dataset partially depicted in Illustration 7 appears.

Illustration 7: Results Dataset – Min() Leveraged to Deliver More Sophistication (Partial View)

In the returned dataset, we see the list of Resellers who have been evaluated as having sales activity in at least one period of Calendar Year 2003. Juxtaposed with these names, we observe the calculated member we have constructed, Lowest Sales (containing the primary use of the Min() function).

NOTE: For examples of the use of Non Empty and Descendants(), see various articles throughout this series. Moreover, for an introduction to the .Members function, see my article MDX Members: Introducing Members and Member.

5.  Select File -> Save MDXQuery2.mdx As ..., name the file MDX063-002.mdx, and place it in the same location used to store the earlier query.

To corroborate the operation of the solution we have proposed above, let’s examine the sales figures concerned for a given reseller over all periods in the year under examination. From this quick test dataset, we can see that our calculated members (each leveraging the Min() function) have served us as expected, both in selection of the appropriate value for Lowest Sales.

6.  Select File --> New from the main menu, as we did earlier.

7.  Select Query with Current Connection from the cascading menu that appears next, once again.

A new tab, with a connection to the Adventure Works cube appears in the Query pane, as before.

8.  Type (or cut and paste) the following query into the Query pane:

```
-- MDX063-3 "Check Query" to Ascertain Solution Effectiveness
SELECT
CROSSJOIN(
{DESCENDANTS( [Date].[Calendar].[Calendar Year].[CY 2003],
[Date].[Calendar].[Month])},
{[Measures].[Reseller Sales Amount]}
)
ON AXIS(0),
{[Reseller].[Reseller Type].[Reseller].[Best o' Bikes]:
[Reseller].[Reseller Type].[Reseller].[Bicycle Exporters]}
ON AXIS(1)
FROM
```

The Query pane appears, with our input, as shown in Illustration 8.

Illustration 8: Verifying Our Results with a “Test Data” Query

We have simply constructed a query to generate the Calendar Year 2003 monthly values for Reseller Sales Amount for a small sample, consisting of a couple of the organization’s resellers, Best o’ Bikes and Bicycle Exporters. We will be able, thereby, to easily identify the “lowest value” of each that represents Lowest Sales value among the months. We can then also see, at a moment’s glance, the month in which these sales took place. We can then compare the results of our sample to the value delivered by our Lowest Sales calculated member in the dataset retrieved by the last query, to determine accuracy – and thereby verify the effectiveness of our approach.

NOTE: For more detail surrounding the CrossJoin() function, see Basic Set Functions: The CrossJoin() Function, another member of my MDX Essentials series at Database Journal.

9.  Execute the query by clicking the Execute button in the toolbar.

The Results pane is, as before, populated by Analysis Services. The dataset partially depicted - only the months July and October 2003 are non-nulls - in Illustration 9 appears.

Illustration 9: Results Dataset – Confirmation Query

In the returned dataset, we see the values we have discussed appearing for each month in Calendar Year 2003 for each of the two sample Resellers (Lowest Sales values are enclosed in red). We also note that the value presented by the Lowest Sales calculated member in our solution for each of the two Resellers agrees to what we can easily see is the smallest value within the confirmation dataset, and that the month within which the “lowest month’s sales” took place in the confirmation dataset agrees to the Lowest Period month returned in our solution. The comparisons appear as shown in composite Illustration 10.

Illustration 10: Results Datasets Composite – Indicating That Our Solution is Effective

The Logistics department representatives express satisfaction with the results, and confirm their understanding of the operation of the Min() function within the context we have presented, among other uses we have discussed in earlier sections. We suggest to our client colleagues that, among numerous possibilities, the Resellers (single, multiple, or ranged, etc.), as well as various components of the Date dimension (Calendar or Fiscal Hierarchy, Year, Semesters, Quarters, Months, etc.) and other components of our query might be parameterized, within their Reporting Services environment. Moreover, we emphasize, we might add other capabilities within the ultimate reporting dataset query.

Suffice it to say that, assuming an “above ordinary” knowledge of the various layers of the Microsoft integrated BI solution, one can obtain many powerful capabilities and features, and knowing “where to put the intelligence” within the sometimes multiple choices can mean highly tuned performance and effective solutions for consumers throughout our organizations. For more of my observations on this subject see Multi-Layered Business Solutions ... Require Multi-Layered Architects.

10.  Experiment with the “test query,” as desired, to examine and compare the values for other Resellers to those delivered by the previous query via the Min() function.

11.  Select File -> Save MDXQuery3.mdx As ..., name the file MDX063-003.mdx, and place it in the same location used to store the earlier query, if and when desired.

12.  Select File -> Exit to leave the SQL Server Management Studio, when ready.

### Summary...

In this article, we introduced and explored the MDX Min() function, one of several aggregate functions available within the MDX toolset, whose general purpose is to deliver a minimum value of a numeric expression that is evaluated over a set. We emphasized that Min() can be leveraged in a wide range of activities, from the simple “generation of minimums” from simple sets of dimensional members to multidimensional juxtapositions we can compose to deliver even more sophisticated results. Moreover, we learned that Min() can serve as an excellent tool to support sophisticated conditional logic, as well as other calculations, to deliver exactly the analysis and reporting presentations required by our clients and employers.

We examined the syntax involved with Min(), and then undertook a couple of illustrative practice examples of uses for the function, generating queries that capitalized upon its capabilities. Throughout our practice session, we briefly discussed the results datasets we obtained from each of the queries we constructed, as well as extending our discussion to other possible options and uses for the concepts we exposed.

Discuss this article in the MSSQL Server 2000 Analysis Services and MDX Topics Forum.