You are on page 1of 17

MDX

:

Introduction
This article explains learning of MDX query in detail. When OLAP cube is designed
and deployed on SSAS engine, we use MDX to read data. OLAP cube contains data in
Cube database. This cube database is different from OLTP relational database. Cube
database contains Datasources, Datasource views, cubes, dimension and mining
structure. Each cube in cube list contains Measure Groups. these measure groups
consist of different measures on which multiple dimension can be applied. I am
assuming you already have available OLAP cube in SSAS engine. If it is not available,
then first download it from Download source section of this article and deploy the
cube. I have already covered OLAP Cube deployment steps in my previous
article Designing SSAS cube. You can also download sample datawarehouse
database from my previous article, Designing SSAS cube.

Background
OLTP database can be queried using T-SQL. T-SQL uses select statement to read data
from table. Similarly, OLAP cube reads data from measures and dimension using
MDX query. MDX has separate syntax to specify multiple dimension and measures in
query. This article covers these syntax and functions in detail. MDX allows to specify
multiple dimensions in single query and can generate result dataset. MDX is
managed query expression which covers different approach to apply dimension on
any measures.

MDXquery1. Open database and click on New Query. .mdx file will be available to write MDX query.Using the Code Connect with SSAS service engine.

Start writing first MDX query.Expand cube to view all available measures and dimensions. .

596.Hide Copy Code SELECT FROM [ADVENTURE WORKS] The above query contains Select statement reading data from OLAP cube [Adventure works]. MDX query to read from specific measures Hide Copy Code SELECT FROM [ADVENTURE WORKS] WHERE [MEASURES].SalesAmount) FROM FactResellerSales S Now.450. Slice Dice and Filter in MDX query .98 value. FactResellerSales table is available in AdventureWorksDW2008R2 database. Designing SSAS cube.[RESELLER SALES AMOUNT] The above MDX query will read cube data from [RESELLER SALES AMOUNT] measure where clause specifies measure/dimension area of cube to which Set is to be slice. The result value is showing $80. it clearly displays that default measure is ResellerSales. You can verify it by checking the below SQL query. It is default assign measure value read by MDX. Hide Copy Code SELECT SUM(S. This database can be downloaded from my previous article.

[product categories].[product categories].[category].[product categories].[geography].[country].Specify measure value in column Hide Copy Code SELECT [MEASURES]. [geography]. Specify non measure member in where clause Hide Copy Code Select { [product]. [measures].[reseller tax amount] The above query will get product dimension wise reseller tax measure data.[RESELLER FREIGHT COST] ON COLUMNS FROM [ADVENTURE WORKS] The above query will show measure [RESELLER FREIGHT COST] data into column. Specify measure in where clause and dimension in column Hide Copy Code --SPECIFYING MEASURES IN WHERE CLAUSE --WHERE CLAUSE TO GET PRODUCT WISE SALE OF SPECIFIC MEASURE Select { [product]. [product].[product categories] } on columns from [adventure works] where [geography]. [product].[product categories] } on columns from [adventure works] where [measures]. [product].[canada] is dimension and not a measure specified in where clause so that where clause accepts dimension as well as measures.[country].[canada].[country].[geography]. Specify multiple member in where Slicer Hide Copy Code Select { [product].[internet sales amount] ) .[geography].[category].[product categories] } on columns from [adventure works] where ( [geography].[canada] The above query will get product wise reseller sales for specific country Canada.[category].

[Sales Territory].[Sales Territory]. [product].[country].[category].[internet sales amount] ) You can also use the below query for except operation. It display internet sales amount of two countries.[country].[australia] }. [customer].[product categories].[product categories] } on columns from [adventure works] where ( [measures].[United Kingdom] }.The above MDX query has multiple members in where Slicer.Canada and Australia.[internet sales amount] ) The above MDX query specified two non measures in slicer. It reads internet sales of specific country Canada.[product categories] } on columns from [adventure works] where ( { [customer]. [product].[customer geography]. { Except( .[country] [Sales Territory].[internet sales amount].[country]. Two non measure dimension in same slicer Hide Copy Code Select { [product].[category].[category]. [measures].[product categories]. [measures]. Except and Minus operation in MDX Hide Copy Code Select { [product].[product categories]. [product].[product categories] } on columns from [adventure works] where ( { [Sales Territory].[canada]. Hide Copy Code Select { [product].[customer geography].

[category] } having [measures]. { [product].[internet sales amount] } on columns. { [product]. It will show internet sales amount of all sales territory except United Kingdom.[Sales Territory].[category] } on rows from [adventure works] The above query will display product wise internet sales amount.[internet sales amount] > 0 on rows from [adventure works] . Filter in MDX query is applied through Filter function. [Sales Territory]. Hide Copy Code --apply filter using filter function Select { [measures].[internet sales amount] } on columns.[country]. [measures]. Product category will be available in rows and internet sales will be available in columns.[product categories]. Show dimension in rows and measures in column in MDX query Hide Copy Code Select { [measures].operator to slice from query.[internet sales amount] >0) } on rows from [adventure works] The above query will display product wise internet sales amount having sales amount greater than 0.[product categories].[United Kingdom] ) } ) The above query uses Except and .[country].[product categories].[internet sales amount] } on columns. { filter([product]. Row level filter can be apply using Having clause in MDX Hide Copy Code Select { [measures].[Sales Territory].[Sales Territory].[category].

[measures]. The condition is applied using And operator in Filter function.[internet sales amount] } on columns. The condition in MDX is specified using IS operator.CURRENTMEMBER IS [product]. Comparing between two measures value in MDX Hide Copy Code Select { [measures].[product categories].[category].[internet sales amount] <750000) } on rows from [adventure works] The above query will show internet sales of all products which have sales amount greater than 500000 and less than 750000. ([product].[product categories].[category].[reseller sales amount]) } on rows from [adventure works] The above query will compare two measures and show all rows where measure value of internet sales is greater than reseller sales. [measures].[category]. Using of IS operator in MDX query Hide Copy Code Select { [measures]. .[Bikes]) ) } on rows from [adventure works] The above query will display sales detail of product category Bikes and Accessories only. { filter([product].[internet sales amount] > [measures].CURRENTMEMBER IS [product].[reseller sales amount] } on columns.[category].[accessories]) OR ([product].[product categories].[product categories]. { filter([product]. [measures].[category].[product categories]. { filter([product].[internet sales amount] } on columns.[internet sales amount].[product categories].[internet sales amount] >500000 AND [measures].Boolean operator used in MDX query to apply row level filter Hide Copy Code Select { [measures].[product categories].

Non Empty to slice NULL rows from MDX result set Hide Copy Code Select { [measures].[measures].[product categories].[internet sales amount] on columns. Hide Copy Code Select {[measures].[product categories].[product categories]. bottomcount( filter([product].[product categories].[reseller sales amount] } on columns. Hide Copy Code Select [measures].5.[internet sales amount] >0 ) on rows from [adventure works] Tops and Bottoms row accessing using MDX Show internet sales amount of all product subcategory. [measures].[internet sales amount].[subcategory] on rows from [adventure works] Show top 5 rows of product subcategory.5) on rows from [adventure works] Show internet sales of top 5 product subcategories using Topcount in MDX.[internet sales amount]) on rows from [adventure works] Show internet sales of bottom 10 product subcategories excluding NULL or 0 values using Bottomcount in MDX. [product].[subcategory]. non empty filter([product].[reseller sales amount]} on columns. [measures].[internet sales amount] on columns.[subcategory].[category].[product categories].[internet sales amount] . topcount([product].[measures].[internet sales amount] on columns. . Hide Copy Code Select [measures]. [measures].[subcategory]. Hide Copy Code Select [measures]. [measures]. topcount([product].[internet sales amount]) on rows from [adventure works] Topsum in MDX query to show all top rows actually formed sum of given value.[internet sales amount]>0) .10.

[internet sales amount]) on rows from [adventure works] The above query shows all product subcategories internet sales which is forming sum of 25000000 amount. Introduction .1000000. bottomsum([product].[product categories]. topsum([product].[subcategory]. Hide Copy Code Select [measures].Hide Copy Code Select [measures].[internet sales amount] on columns.[product categories].[internet sales amount] on columns.[measures]. Bottomsum in MDX query to show least rows require to form sum of specific value.[measures].[internet sales amount]) on rows from [adventure works] The above query shows all product subcategories internet sales which is forming sum of 1000000 amount.[subcategory].25000000.

I personally assume. Calculation process in MDX includes arithmetical and logical values process with existing measures values. Background OLAP cube contains multiple different measures. I have already covered basic MDX query. [measures].[customer sales] as [measures]. Calculation in MDX Query After writing basic MDX query and getting familiar with syntax of MDX. you will write MDX query more comfortable you will be on OLAP cube. Dimensions available in OLAP cube are collection of attributes. With Member clause allow to create scope member in MDX Hide Copy Code With member [Measures]. Writing complex OLAP cube helps you to prepare business solution easily. { [date].[retailer sales] } on columns.[internet sales amount] Member [measures]. Till now.[My Member] as "Datawarehouse Consultant" Select { [measures]. we can start for complex MDX query. we have used existing measures and dimensions of OLAP cube in MDX query. These measures can be queried through different available dimensions. If you require basics of MDX query. specify range based calculation with measure value and date wise calculation with measure value. please do read my article Reading OLAP cube using MDX query Part 1. We may require some time calculated measure or calculated dimension for our business process. This can be achieved through With Member clause in MDX.[calendar year] } on rows from [adventure works] .[My Member] } ON Columns From [Adventure works] The above MDX query will create scope member [My Member] in current scope.This article contains calculation process used in MDX. This article will cover calculation based on attribute relationship available in dimension. OLAP cube contains definition of attribute relationship of dimension. Create alias of existing member using With Member Hide Copy Code With Member [measures].[calendar].[customer sales].[reseller sales amount] Select { [measures]. strength in MDX query makes you more comfortable to work on OLAP cube. More different way. Filter process in MDX query and different Slicing feature in MDX query in my previous article Reading OLAP cube using MDX query Part 1.[retailer sales] as [measures].

[total sales] } on columns. [measures].[calendar year] } on rows from [adventure works] In the above MDX query example.[reseller sales amount].format_string="#.###.[internet sales amount]+ _ [measures].[retailer sales] as [measures]. [Total sales] is a new member calculated using With Member clause.###. { [date].[reseller sales amount] Member [measures]. { [date]. Named set create using With Set clause Long MDX expression can alias with Set name using With Set clause.[internet sales amount].format_string="#. Formatting of existing member using With Member Hide Copy Code With Member [measures]. Alias helps to access this long name with some small name.[calendar year] } on rows from [adventure works] In the above example.[retailer sales].00€" Member [measures].###.[calendar].[calendar].[Total Sales] as [measures].[Total Sales] as [measures].[reseller sales amount].[retailer sales] as [measures]. [measures].[customer sales].[internet sales amount]+ [measures].00€" Member [measures]. Calculation using With Member Hide Copy Code With Member [measures].The above query creates alias [Customer Sales] and [Retailer Sales] for existing member. This step actually helps when required member is available in multiple level of measure group. [measures].[customer sales] as [measures].[total sales] } on columns.00€" Select { [measures]. all sales figure will display in € format.[customer sales]. Hide Copy Code With .[internet sales amount] Member [measures].format_string="#. [measures].[customer sales] as [measures].[reseller sales amount] Select { [measures].[retailer sales].

[measures].00€" Member [adventure works].[internet sales amount]+ _ [measures].[internet sales amount].[Calendar Year]. [measures].[Calendar].[Total Sales] as [measures].Set [Not 2008] as [Date].###.[customer sales] as [measures]. This named set contains all calendar years from[CY 2001] to [CY 2007].[customer sales] . Note: We must require to provide cube name before specifying member name in Create Member.00€" Member [measures].format_string="#.[Calendar].[total sales] } on columns. I have created three members for the entire session.###. [CY 2007] Member [measures].[retailer sales]. I have create [Not 2008] as named set. [measures].[internet sales amount].[customer sales] as [measures].[customer sales].###.[CY 2001] : [Date]. { [Date].[Total Sales] as [measures].00€" Member [measures].[Calendar Year]. [measures].format_string="#.[measures].###.format_string="#.[measures].00€" Member [adventure works].###.###.[retailer sales] as [measures]. I have consumed all new members created in the previous example through Create Member clause. Now.format_string="#.[total sales] } on columns. Hide Copy Code Select { [measures].00€" In the above example.[retailer sales] as [measures]. Create Member in MDX to create member or set for entire session Hide Copy Code Create Member [adventure works].[customer sales].[Calendar Year] } on rows from [adventure works] In the above example.[Calendar]. we can use these members in the entire session.[reseller sales amount].[reseller sales amount].format_string="#.[reseller sales amount].[retailer sales]. { [Not 2008] } on rows from [adventure works] In the above example.[internet sales amount]+ _ [measures].[reseller sales amount].[measures]. Drop member created using Create Member Hide Copy Code drop member [adventure works]. [measures].00€" Select { [measures].format_string="#.

[measures].Nextmember } ON Columns From [Adventure Works] Where [Measures].[Fiscal].[FY 2007].1.[Fiscal Year].[Fiscal]. [Date]. Working with time dimension in MDX query Hide Copy Code Select { [Date].[measures].[FY 2007].[Fiscal Year].[FY 2007].[Fiscal].[Date].[retailer sales] go drop member [adventure works]. I have dropped all members created using Create Member clause.[Internet Sales Amount] The above example is using PrevMember and NextMember property to access previous and next member of any dimension.[Fiscal].[Fiscal Year]. Hide Copy Code Select { .[Fiscal Year].[Fiscal].[Internet Sales Amount] The above query will display Sales figure of financial year 2007.[FY 2007]) } ON Columns From [Adventure Works] Where [Measures].go drop member [adventure works]. OpeningPeriod function and ClosingPeriod function. ParallelPeriod function in MDX also returns prev/next member based on given parameter. Hide Copy Code Select { ParallelPeriod([Date].[Fiscal].[Internet Sales Amount] The above example returns previous year member of [FY 2007] because parameter value given toParallelPeriod function is 1.[FY 2007] } ON Columns From [Adventure Works] Where [Measures].[Fiscal Year].[Total Sales] In the above example.[Fiscal Year]. Previous and Next member access in MDX Hide Copy Code Select { [Date]. [Date].Prevmember.

[Category] }ON rows From [Adventure Works] Where [Measures].[Category].[Internet Sales Amount] In the above example. { [Product]. { [Product].[Category] }ON rows From [Adventure Works] Where [Measures].[Fiscal]. { [Product].[Fiscal Year]) } ON Columns From [Adventure Works] Where [Measures].OpeningPeriod([Date]. Specify range in member using : (colon) operator Hide Copy Code Select { OpeningPeriod([Date].[Internet Sales Amount] Openingperiod function returns first member of given dimension and Closingperiod function returns last member of given dimension. ClosingPeriod([Date]. PeriodsToDate function to specify range in member Hide Copy Code --display financial year wise sales Select { PeriodsToDate([Date].[Fiscal Year]) } ON Columns. Starting Range in MDX can be specify using NULL value Hide Copy Code Select { NULL: ClosingPeriod([Date]. initial range is specified using value NULL.[Fiscal].[Category] }ON rows From [Adventure Works] Where [Measures].[Internet Sales Amount] .[Fiscal].[Fiscal].[Fiscal Year].[Fiscal].[Fiscal Year]).[Internet Sales Amount] The above example is using : operator to specify beginning member to end member of dimension.[Category]. I have usedOpeningperiod function for first member and Closingperiod function for last member.[Fiscal].[Fiscal].[FY 2008]) } ON Columns.[(All)].[Category].[Fiscal Year]): ClosingPeriod([Date].[Date].[Fiscal Year]) } ON Columns.

[Category] }ON rows From [Adventure Works] Where [Measures].[Category] }ON rows From [Adventure Works] Where [Measures].[Category]. { [Product]. YTD covers Year till date members of dimension.[Month].[Internet Sales Amount] In the first example.[Category] }ON rows From [Adventure Works] Where [Measures].[Fiscal].[Fiscal Year]. Specify range in MDX using LastPeriod function Hide Copy Code --display previous 3 member Select { LastPeriods(3. While in second example when we have provided financial month in range.[Internet Sales Amount] --display next 3 member Select { LastPeriods(-3.[Category].[DECEMBER 2006]) } ON Columns.[Date].[Fiscal]. { [Product].[Category] }ON rows From [Adventure Works] Copy Code .[Date].[Category].--display month wise sales of given financial year Select { PeriodsToDate([Date].[FY 2008]) } ON Columns.[Date]. Specify date range in dimension using YTD. { [Product].[Fiscal Year]. { [Product]. QTD covers Quarter till date members and MTD covers Month till date members of given dimension.[Fiscal]. PeriodtoDate function displays sales value from first available financial year to financial year 2008.[Fiscal].[Internet Sales Amount] The above example displays that positive value in LastPeriods function shows last member and negative parameter value in LastPeriods function shows next member in given dimension.[Category].[Calendar Year].QTD and MTD function. Hide Shrink --YTD for Year till date Select { YTD([Date]. it will show sales of first financial month of year upto given financial month of year.[Fiscal Year].[CY 2008]) } ON Columns.[FY 2008]) } ON Columns.[Calendar].

[Category] }ON rows From [Adventure Works] Where [Measures]. { [Product].Where [Measures].[Date].[Category].[July 2.[Category]. QTD and MTD function.2006]) } ON Columns.[Internet Sales Amount] --MTD for month till date Select { MTD([Date].[DECEMBER 2006]) } ON Columns. { [Product]. .[Calendar].[Category] }ON rows From [Adventure Works] Where [Measures].[Calendar].[Month].[Internet Sales Amount] --QTD for quarter till date Select { QTD([Date].[Internet Sales Amount] The above example displays date range specification using YTD.