Thursday, July 15, 2010

MDX Puzzle #3 Solution

Sorry that it’s taken me so long to write this post, but I have been a little busy with the SQL Lunch.  I am back now, so let’s solve this puzzle.  This puzzle introduced a new keyword, WITH, that can be used to create a calculated member that is only available for a single MDX query.  Note that, after the query is finished executing the calculated member no longer exists.  Also, introduced are three functions ROOT, AGGREGATE, and TOPCOUNT, which will all be explain later in this posting. 

So, here is what I started with.  This query satisfies these requirements:

1.  Internet Order Quantity

2.  Product

3.  Return only the TOP 10 Products based on the Internet Order Quantity

image

One thing that is new is the use of TOPCOUNT in the Rows section of the query.  TOPCOUNT behaves similar to TSQLs TOP(), but it requires three arguments instead of one.  It requires a Set Expression, which is a valid MDX expression that returns a set.  In this example, the set is all the Children of the product dimension.  The next argument is the Count, which is the number that specifies how many tuples will be returned.  Finally, it expects a Numeric Expression, which is the value that will be used to determine which set is returned.  This value is typically an MDX expression that returns a value.  The TOPCOUNT sorts the set in descending order and returns the specified number of elements (the Count argument) with the highest values (the Numeric Expression).

Now let’s create the calculated member.  Here is the query that was used:

image

You will notice the use of the WITH keyword that was explained earlier and the MEMBER clause.  Two calculated members are created in the above query.  The first uses the AGGREGATE() and ROOT() functions to calculate the total of all Internet Orders.  The second performs simple division, dividing Internet Order Quantity by the calculated total from the first member to obtain the Percentage of Total Orders.

The AGGREGATE and ROOT() are two new functions in this series.  The AGGREGATE function accepts two arguments.  The first is a Set_Expression, which in this example is ROOT().  The second argument, which is optional, is a Numeric_Expression.  The Numeric_Expression is typically an MDX expression that returns a numbers.  For this example, the Internet Order Quantity measure was used.  the ROOT() function was for the Set_Expression because it returns ALL member from each attribute hierarchy in the cube.  As a result, the total Order Quantity for the entire cube will be returned.  One thing to note about the ROOT() function is that you can limit its results by passing either a Dimension or Tuple Expression as an argument. 

Now to complete the puzzle, take the calculated members MDX query and paste it directly above the SELECT statement.  Then add the Percentage of Total calculation to the ON COLUMNS section of the SELECT statement.  Finally, you will have the solution.  See the query below:

image

One thing that I have realized is that, just like T-SQL, there are several ways to solve a query with MDX.  Once I have finished the journey of mastering the art of writing MDX, I will begin down the path of performance tuning and writing efficient MDX queries.

Talk to you soon,

Patrick LeBlanc, SQL Server MVP, MCTS

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company

Monday, July 12, 2010

Speaking at Greater New Orleans .Net User Group (GNO.NET)

This week I will speaking at the Greater New Orleans .Net User Group.  My topic is Introduction to the SQL Server Profiler.  If you want to learn some tips and tricks that you can use when trying to identify performance problems with your SQL Server stop by the meeting.  Also, I will be giving away an MSDN subscription at the end of my presentation.  Here are the meeting details.

Meeting URL:  http://tinyurl.com/0710-gno-net

Time:  6:30 PM CST

Location:  New Horizons, 2800 Veterans Memorial, BLVD, Metairie, LA 7002

Hope to see you all there. 

P.S.  I will be giving away a free MSDN subscription to one lucky participant.

Talk to you soon,

Patrick LeBlanc, SQL Server MVP, MCTS

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company.

Thursday, July 8, 2010

Free Data Warehouse Training – Let's Get Dimensional

Join Adam Jorgensen, tomorrow on the SQL Lunch to learn about Dimensional Modeling.  Go to SQL Lunch and add this event to your calendar or use the link in this posting.  To receive notifications about upcoming SQL Lunches please go here.  Every week this month we will be hosting a lunch time meeting. 

Title:  #27 - Let's Get Dimensional

Add to Outlook:  Add to Calendar

Date:  7/22/2010

Speaker:  Adam Jorgensen

Join Meeting:  https://www.livemeeting.com/cc/usergroups/join?id=Z9N87J&role=attend

Description: Learn the basics or dimensional modeling, the foundation for any good data warehouse, with Adam Jorgensen on SQLLunch. Adam will take us through why how dimensional modeling is different from your typical applications database, why it’s different, and some mistakes to avoid. We will review some existing models and take your questions on you modeling challenges. We’ll review common scenarios and discuss why they are the best approach.

BIO:  Adam Jorgensen , MBA, MCDBA, MCITP: BI has over a decade of experience leading organizations around the world in developing and implementing enterprise solutions. His passion is finding new and innovative avenues for clients and the community to embrace business intelligence and lower barriers to implementation. Adam is also very involved in the community as a featured author on SQLServerCentral, SQLShare, as well as a regular contributor to the SQLPASS Virtual User Groups for Business Intelligence and other organizations. He regularly speaks at industry group events, major conferences, Code Camps, and SQLSaturday events on strategic and technical topics.

Talk to you soon,

Patrick LeBlanc, SQL Server MVP, MCTS

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company.

Tuesday, July 6, 2010

Free SSIS Training – SQL Lunch #24 (Looping in SSIS)

Join Brad Schacht this week on the SQL Lunch to learn about Looping in SSIS.  Go to SQL Lunch and add this event to your calendar or use the link in this posting.  To receive notifications about upcoming SQL Lunches please go here.  Every week this month we will be hosting a lunch time meeting. 

Title:  #24 Looping in SSIS

Add to Outlook:  Add to Calendar

Speaker:  Brad Schacht

Join Meeting:  https://www.livemeeting.com/cc/usergroups/join?id=SBMB3K&role=attend

Description:  In this session Brad will walk you through the loops available in SQL Server Integration Services. Topics to be covered include the ForLoop and the value it provides, as well as the most common uses for the ForEach Loop; such as looping over files. Setup and configuration will be discussed along with when a loop should be used. We will also discuss how to use these loops to dynamically name a file for archiving after it is done being used inside the package.

BIO:  Brad is a BI Consultant and Trainer for Pragmatic Works. His experience on the Microsoft BI platform includes DTS, SSIS, Reporting, and migrations and conversions. His background in creating custom solutions for clients and partners provides great experience for delivering real-world value through his courses. Brad uses this experience to make the topics real for those he’s working with and teaching. Brad also participates as a speaker at events such as SQL Saturday and is an active member of the Jacksonville SQL Server User’s..

Talk to you soon,

Patrick LeBlanc, SQL Server MVP, MCTS

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company.

MDX Puzzle #3

The next puzzle comes from a BIDN.com forum post.  Here are the requirements:

Columns:  Internet Order Quantity and Percentage Of Total (Calculation)

Rows: Product

Filter:  Return only the TOP 10 Products based on Internet Order Quantity.

Hint:  Use the WITH MEMBER statement to perform the calculation.  In addition, you will need to you the ROOT function or [ALL Products] to get the Total Quantity Ordered for the calculation.  Your result set should resemble the following:

image

Remember, don’t post you solutions here.  Save them for my solution post.  I will post it along with the steps that was taken to solve the puzzle in a couple of days.  

Don’t forget to check back in a couple days for the solution.

Talk to you soon,

Patrick LeBlanc, SQL Server MVP, MCTS

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company.

Monday, July 5, 2010

MDX Puzzle #2 Solution

This puzzle was a little more challenging than the first, but it was definitely fun and a good learning experience.  It introduced a new method that allows you to create session scoped calculation that can be used in your MDX query.  You can actually take the code used in the CREATE MEMBER statement (that will be explained in later puzzles) and add it to your cube as a CALCULATED MEMBER.

First, let’s address the simple parts of the requirements.  The following query satisfies the following:

  1. Columns:  Internet Sales
  2. Rows:  Calendar Years
  3. Filter:  Only Show United States Bike Sales

image

Now, above this statement in your query window you can use the CREATE MEMBER or WITH MEMBER statement to create a calculated member to be used in the query.  In this puzzle I will be using the CREATE MEMBER statement.  I will use the WITH MEMBER statement in later puzzles.  The CREATE MEMBER statement defines a calculated member that is available throughout the session and can be used by multiple queries within the session.  This statement will be used to create the YearlyGrowth calculated member, which will be added to the above query.  Here is the statement:

image

You should note that a CASE statement is used in the calculation.  There are three conditions in the case.  The first condition will ensure that the query avoids a divide-by-zero error by checking the previous years sales.  If the previous years sales is empty then the calculation is not performed and the value retuned is NULL.  The second condition checks to see if the sales for the current year is empty.  As with the previous year, if the current year is empty a NULL value is returned.  Finally, if neither condition is met the calculation is performed. 

There are also a few new functions that must be explained.  The first is IsEmpty.  The IsEmpty function evaluates whether or not a cell value is empty.  The next function is PrevMember.  The PrevMember function returns the previous member in the level that contains the specified member.  In the example, I use it to return the previous years sales.  Finally, FORMAT_STRING, which not a function, but an option for the CREATE MEMBER statement, is used to specify how the returned value should be formatted.

If you couple these two statements in the same query window, running the create member statement first then the query, you will completely satisfy the requirements of the query.  Here is the solution:

CREATE MEMBER [Adventure Works].Measures.YearlyGrowth 


AS 


 


'


CASE 


When IsEmpty


(


    ([Internet Sales Amount], [Date].[Calendar Year].PrevMember)


)


Then Null


 


When IsEmpty


(


    [Internet Sales Amount]


)


Then Null


 


 ELSE


(


    


    (


        ([Internet Sales Amount])-([Internet Sales Amount], [Date].[Calendar Year].PrevMember)


    )


    /([Internet Sales Amount], [Date].[Calendar Year].PrevMember)


)


END',


FORMAT_STRING='Percent';


 


SELECT 


    NON EMPTY{[Measures].[Internet Sales Amount], YearlyGrowth


 


    } ON COLUMNS,


    


    NON EMPTY(


         [Date].[Calendar].[Calendar Year].Members) ON ROWS


FROM [Adventure Works]


WHERE


    (


        [Sales Territory].[Sales Territory].[Country].&[United States],


        [Product].[Category].[Bikes]


    );





In the above query I added the calculated member, Yearly Growth, to the list of columns.  If you need to update the calculated member, simply change the CREATE to an UPDATE.  Then run the statement and finally rerun your query.  Unlike T-SQL, the two MDX statements must be run separately.  Stay tuned for Puzzle #3. 

Talk to you soon,



Patrick LeBlanc, SQL Server MVP, MCTS



Founder www.TSQLScripts.com and www.SQLLunch.com.



Visit www.BIDN.com, Bring Business Intelligence to your company.

Thursday, July 1, 2010

SQL Server MVP - Are you kidding me?

I received an email today stating that I had been selected as a Microsoft SQL Server MVP for 2010.  This is my first MVP award and I am elated to become part of such a distinguished group.  What a great community!!!!

Thanks to all those that nominated me and thanks to the MVP team!

Talk to you soon,

Patrick LeBlanc, SQL Server MVP

Founder www.TSQLScripts.com and www.SQLLunch.com.

Visit www.BIDN.com, Bring Business Intelligence to your company.