Performing Common MDX-related Tasks

Exclusive offer: get 50% off this eBook here
MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook — Save 50%

80 recipes for enriching your Business Intelligence solutions with high-performance MDX calculations and flexible MDX queries with Microsoft SQL Server 2008 R2 Analysis Services with this book and eBook

£18.99    £9.50
by Tomislav Piasevoli | August 2011 | Enterprise Articles Microsoft

This article by Tomislav Piasevoli, author of MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook, discusses the common MDX tasks and one or more ways to solve them or deal with them appropriately. We'll cover basic principles and approaches such as how to skip an axis and prevent common errors, how to set the default member of a hierarchy, and how to format cell foreground and background colors based on the value in cells.

Specifically, we will cover:

  • Skipping axis
  • Handling division by zero errors
  • Setting special format for negative, zero, and null values
  • Applying conditional formatting on calculations
  • Setting default member of a hierarchy in MDX script

 

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

More than 80 recipes for enriching your Business Intelligence solutions with high-performance MDX calculations and flexible MDX queries in this book and eBook

        Read more about this book      

(For more resources on Microsoft SQL Server, see here.)

 

Skipping axis

There are situations when we want to display just a list of members and no data associated with them. Naturally, we expect to get that list on rows, so that we can scroll through them nicely. However, the rules of MDX say we can't skip axes. If we want something on rows (which is AXIS(1) by the way), we must use all previous axes as well (columns in this case, which is also known as AXIS(0)).

The reason why we want the list to appear on axis 1 and not axis 0 is because a horizontal list is not as easy to read as a vertical one.

Is there a way to display those members on rows and have nothing on columns? Sure! This recipe shows how.

Getting ready

Follow these steps to set up the environment for this recipe:

  1. Start SQL Server Management Studio (SSMS) or any other application you use for writing and executing MDX queries and connect to your SQL Server Analysis Services (SSAS) 2008 R2 instance (localhost or servername\instancename).
  2. Click on the New Query button and check that the target database is Adventure Works DW 2008R2.

How to do it...

Follow these steps to get a one-dimensional query result with members on rows:

  1. Put an empty set on columns (AXIS(0)). Notation for empty set is this: {}.
  2. Put some hierarchy on rows (AXIS(1)). In this case we used the largest hierarchy available in this cube – Customer hierarchy of the same dimension.
  3. Run the following query:

    SELECT
    { } ON 0,
    { [Customer].[Customer].[Customer].MEMBERS } ON 1
    FROM
    [Adventure Works]

How it works...

Although we can't skip axes, we are allowed to provide an empty set on them. This trick allows us to get what we need – nothing on columns and a set of members on rows.

There's more…

Notice that this type of query is very convenient for parameter selection of another query as well as for search. See how it can be modified to include only those customers whose name contains the phrase "John":

SELECT
{ } ON 0,
{ Filter(
[Customer].[Customer].[Customer].MEMBERS,
InStr(
[Customer].[Customer].CurrentMember.Name,
'John'
) > 0
)
} ON 1
FROM
[Adventure Works]

In the final result, you will notice the "John" phrase in various positions in member names:

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

The idea behind

If you put a cube measure or a calculated measure with a non-constant expression on axis 0 instead, you'll slow down the query. Sometimes it won't be so obvious, sometimes it will. It will depend on the measure's definition and the number of members in the hierarchy being displayed. For example, if you put the Sales Amount measure on columns, that measure will have to be evaluated for each member in the rows. Do we need those values? No, we don't. The only thing we need is a list of members; hence we've used an empty set. That way, the SSAS engine doesn't have to go into cube space. It can reside in dimension space which is much smaller and the query is therefore more efficient.

Possible workarounds

In case of a third-party application or a control which has problems with this kind of MDX statement (i.e. expects something on columns and is not working with an empty set), we can define a constant measure (a measure returning null, 0, 1 or any other constant) and place it on columns instead of that empty set. For example, we can define a calculated measure in the MDX script whose definition is 1, or any other constant value, and use that measure on the columns axis. It might not be as efficient as an empty set, but it is a much better solution than the one with a regular (non-constant) cube measure like the Sales Amount measure.

 

Handling division by zero errors

Another common task is handling errors, especially division by zero type of errors. This recipe offers a way to solve that problem.

Not all versions of Adventure Works database have the same date range. If you're not using the recommended version of it, the one for the SSAS 2008 R2, you might have problems with queries. Older versions of Adventure Works database have dates up to the year 2006 or even 2004. If that's the case, make sure you adjust examples by offsetting years in the query with a fixed number. For example, the year 2006 should become 2002 and so on.

Getting ready

Start a new query in SQL Server Management Studio and check that you're working on Adventure Works database. Then write and execute this query:

WITH
MEMBER [Date].[Calendar Year].[CY 2006 vs 2005 Bad] AS
[Date].[Calendar Year].[Calendar Year].&[2006] /
[Date].[Calendar Year].[Calendar Year].&[2005],
FORMAT_STRING = 'Percent'
SELECT
{ [Date].[Calendar Year].[Calendar Year].&[2005],
[Date].[Calendar Year].[Calendar Year].&[2006],
[Date].[Calendar Year].[CY 2006 vs 2005 Bad] } *
[Measures].[Reseller Sales Amount] ON 0,
{ [Sales Territory].[Sales Territory].[Country].MEMBERS }
ON 1
FROM
[Adventure Works]

This query returns 6 rows with countries and 3 rows with years, the third row being the ratio of the previous two, as its definition says.

The problem is that we get 1.#INFM on some cells. To be precise, that value (the formatted value of infinity), appears on rows where the CY 2005 is null. Here's a solution for that.

How to do it...

Follow these steps to handle division by zero errors:

  1. Copy the calculated member and paste it as another calculated member. During that, replace the term Bad with Good in its name, just to differentiate those two members.
  2. Copy the denominator.
  3. Wrap the expression in an outer IIF() statement.
  4. Paste the denominator in the condition part of the IIF() statement and compare it against 0.
  5. Provide null value for the True part.
  6. Your initial expression should be in the False part.
  7. Don't forget to include the new member on columns and execute the query:

    MEMBER [Date].[Calendar Year].[CY 2006 vs 2005 Good] AS
    IIF ([Date].[Calendar Year].[Calendar Year].&[2005] = 0,
    null,
    [Date].[Calendar Year].[Calendar Year].&[2006] /
    [Date].[Calendar Year].[Calendar Year].&[2005]
    ),
    FORMAT_STRING = 'Percent'

  8. The result shows that the new calculated measure corrects the problem – we don't get errors (the rightmost column, compared to the one on its left):

    MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

How it works...

A division by zero error occurs when the denominator is null or zero and the numerator is not null. In order to prevent this error, we must test the denominator before the division and handle the case when it is null or zero. That is done using an outer IIF() statement.

It is enough to test just for zero because null = 0 returns True.

There's more...

SQLCAT's SQL Server 2008 Analysis Services Performance Guide has lots of interesting details regarding the IIF() function:
http://tinyurl.com/PerfGuide2008

Additionally, you may find Jeffrey Wang's blog article useful in explaining the details of the IIF() function:
http://tinyurl.com/IIFJeffrey

Earlier versions of SSAS

If you're using a version of SSAS prior to 2008 (that is, 2005), the performance will not be as good. See Mosha Pasumansky's article for more info:
http://tinyurl.com/IIFMosha

 

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook 80 recipes for enriching your Business Intelligence solutions with high-performance MDX calculations and flexible MDX queries with Microsoft SQL Server 2008 R2 Analysis Services with this book and eBook
Published: August 2011
eBook Price: £18.99
Book Price: £30.99
See more
Select your format and quantity:

 

        Read more about this book      

(For more resources on Microsoft SQL Server, see here.)

 

Setting special format for negative, zero and null values

The FORMAT_STRING property is used for specifying how a regular or calculated member (usually a measure) should be presented and what its FORMATTED_VALUE should look like. There are some predefined formats such as Standard, Currency, or Percent, but we can also specify our own using the right combination of characters.

Most people are unaware of the fact that there are actually 4 sections of the format string for numeric values and 2 sections for strings. In this recipe we'll see how to set the format for negative, zero, or null values.

Getting ready

Follow these steps to set up the environment for this recipe:

  1. Open Business Intelligence Development Studio (BIDS) and then open the Adventure Works DW 2008 solution.
  2. Double-click the Adventure Works cube and go to the Calculations tab.
  3. Choose Script View.
  4. Position the cursor at the end of the script and create a new calculated measure as follows:

    Create Member CurrentCube.[Measures].[Gross Profit formatted]
    As [Measures].[Sales Amount] -
    [Measures].[Total Product Cost],
    Associated_Measure_Group = 'Sales Summary';

That's actually the same definition as the definition of the Gross Profit measure. We have created a clone of that measure using a different name so that we can compare them later and see the formatting effect in action.

How to do it...

Follow these steps to set a custom format:

 

  1. Add the Format_String property for that measure.
  2. Be sure to specify it as below, using 4 sections separated by a semi-colon (;):

    Create Member CurrentCube.[Measures].[Gross Profit formatted]
    As [Measures].[Sales Amount] -
    [Measures].[Total Product Cost],

    Format_String = "#,##0;- #,##0;0;n/a",

    Associated_Measure_Group = 'Sales Summary';

  3. Save and deploy (or just press the Deploy MDX Script icon if you're using BIDS Helper).
  4. Go to the Cube Browser tab. Reconnect and click on the Show Empty Cells button.
  5. Put Promotion Category level on rows. Put Gross Profit and the new Gross Profit formatted measures on columns. Both measures have the same values, but they are formatted differently, as shown in the following image:

    MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

  6. Notice that the new measure shows n/a for null values and uses minus sign for negative ones. In addition to that, it removes decimal part of numbers.

How it works...

The four sections of the format string for numeric values are as follows: the first is for positive numbers, the second is for negative numbers, the third is for the zero value, and the fourth is for null values.

Usually we provide a format string for one section only. However, when required, we can use additional sections and provide formatting there as well. In the example, we eliminated decimals from the value, emphasized negative values with a space before a minus sign, and provided n/a for null values.

There's more...

Another way of specifying format string is by using the Format_String() function inside the MDX script:

Format_String( [Measures].[Gross Profit formatted] ) =
"#,##0;;;-";

By the way, the Adventure Works DW 2008R2 database has a similar example at the end of the MDX script.

We can omit the format of one section by closing it with a semicolon. In the expression above, the format has been specified for positive and null values only. The negative and zero values will retain their default format.

In fact, the format string can be set for several measures that way.

Format_String( { [Measures].[Gross Profit],
[Measures].[Gross Profit formatted] } ) =
"#,##0;;;-";

Finally, the set of members doesn't have to be explicit. It can be obtained using MDX calculations. That might be a nice way to handle and maintain formats for all measures in a cube if there's an order with prefixes/suffixes/special characters inside their names. For example, this code shows how to search for a specific pattern in measures names and apply an appropriate format in case of a hit.

Format_String( Filter( Measures.ALLMEMBERS,
InStr( Measures.CurrentMember.Name,
'Ratio' ) > 0 )
) = 'Percent';

Format_String( Filter( Measures.ALLMEMBERS,
InStr( Measures.CurrentMember.Name,
'Amount' ) > 0 )
) = '#,##0.00';

Tips and tricks

MDX expressions can be used inside the FORMAT_STRING property. The calculation should return a string value which will then be used as a format string. Note that only the values of cells are cached by Analysis Services. When complex expressions are used for the FORMAT_STRING property, it may improve performance if you wrap that expression in a calculated measure. You can then use the calculated measure in the assignment to the FORMAT_STRING property.

A friendly warning

Remember never to put zero values inside your cube instead of empty values or your measure will become dense, always returning a non-null value and the performance will suffer because many MDX functions will not be able to operate in bulk mode by taking advantage of the sparsity of the measure.

If it is required that null values are shown as zeros, then leave them as nulls and use the format string instead. Setting the NullHandling property to Preserve on the measure's source column preserves the null value instead of converting it to zero.

Troubleshooting formatted values

By default, a query with no CELL PROPERTIES returns VALUE and FORMATTED_VALUE, which means the data is returned in two shapes – raw and formatted. And such are almost all queries. However, if we explicitly omit the FORMATTED_VALUE property from cell properties, we won't have formatted values. The success of this recipe depends therefore on the SSAS front end you're using and its way of displaying values.

In case of a problem, be sure to check whether there's an option in the program's connection or its display properties which can turn this on or help in another way. Sometimes you'll be lucky, other times you won't. For example, only the first three sections work in Excel 2007 and Excel 2010. The fourth section is simply ignored.

You can find more information about it on MSDN, on the Using Cell Properties (MDX) page:
http://tinyurl.com/CellProperties

 

Applying conditional formatting on calculations

Sometimes we want to emphasize cells based on their values. That way data analysis becomes easier because we combine best of charts and tables – we still see the values while we have additional color information about the value in each cell.

A typical case is highlighting the background of cells with green or red color for good or bad results, respectively. It's a pretty trivial operation in Excel and it's not that hard in MDX either. This recipe demonstrates how to do this.

Getting ready

Open BIDS and verify you have the Gross Profit formatted measure defined in the previous section, Setting special format for negative, zero and null values. If not, define the measure like this:

Create Member CurrentCube.[Measures].[Gross Profit formatted]
As [Measures].[Sales Amount] -
[Measures].[Total Product Cost],
Format_String = "#,##0;;;-",
Associated_Measure_Group = 'Sales Summary';

How to do it…

Follow these steps to apply conditional formatting:

  1. Locate the measure's definition and position of the cursor at the beginning of any line between the definition and the end of the measure.
  2. Add this part inside.

    Fore_Color = RGB(255, 255, 255),
    Back_Color = case
    when [Measures].CurrentMember > 0
    then RGB(0, 128, 0)
    when [Measures].CurrentMember < 0
    then RGB(128, 0, 0)
    else RGB(100, 100, 100)
    end,

  3. Save and deploy (or just press Deploy MDX Script icon if you're using BIDS Helper).
  4. Go to Cube Browser tab. Reconnect and click on the Show Empty Cells button.
  5. Put the Promotion attribute hierarchy on rows. Put Gross Profit and the new Gross Profit formatted measures on columns. Notice the effect of the format string in the following image. Positive values are colored green, negative ones have become maroon and everything else is grey.

    MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook

 

MDX with Microsoft SQL Server 2008 R2 Analysis Services Cookbook 80 recipes for enriching your Business Intelligence solutions with high-performance MDX calculations and flexible MDX queries with Microsoft SQL Server 2008 R2 Analysis Services with this book and eBook
Published: August 2011
eBook Price: £18.99
Book Price: £30.99
See more
Select your format and quantity:

 

        Read more about this book      

(For more resources on Microsoft SQL Server, see here.)

 

How it works...

The FORE_COLOR property can be applied to any calculated member, the same as the BACK_COLOR property. Just like with the FORMAT_STRING property, we can provide a constant value or an expression. If we provide the expression, the color varies based on what we specified in that expression. If it's a constant, the color remains on all the cells.

In this example, we specified a green background (lighter shade) for positive values, dark red for negative values (dark shades) and grey for the rest (zero and null). Since the background became dark, we changed the font color (or foreground) to white, to keep the contrast high.

The value to be assigned is a number derived by multiplying the factors of 3 colors, components and their values. RGB function found in VBA assembly comes to the rescue here, so we don't have to do that math. That assembly is available by default and registered on every SSAS server.

The arguments of RGB() function are values of intensity of red, green and blue color, in that order. Higher values represent lighter colors, lower values represent darker ones. For example, the black color is (0, 0, 0), whereas white is (255, 255, 255). Everything in between is given to you to experiment with. Take some time and try it!

There's more...

The foreground and background colors can be changed for regular cube measures as well. Since that property is not directly exposed in the GUI, we have to use the Fore_Color() and Back_Color() functions in MDX script. Here's one example:

Back_Color( [Measures].[Order Quantity] ) =
RGB(200, 200, 100);

Tips and tricks

There's a color picker in the Calculation tab of the cube editor. When you operate in the Form View, two color pickers are available, one for the Fore color property of the measure and the other for the Back color property of the measure. Both are found under the Color Expressions section.

When you're using the Script View, the color picker is available in the toolbar.

The color picker returns a single value for a particular color but it also specifies the RGB values in the comment. You may find using the RGB values more convenient. If so, simply delete the single value and apply the RGB() function on RGB values instead.

Advanced graphical programs have color-picker features which lets you point to any dot on the screen and pick its color. As before, RGB values can be read and used in the calculations. This saves you from having to find a particular color if that color is already available somewhere, that is in the company brochure, an Excel table, chart, etc.

Finally, here are a few sites to help you with colors and their names:

500+ Named Colours with rgb and hex values:
http://tinyurl.com/RGBColors1

RGB to Color Name Mapping:
http://tinyurl.com/RGBColors2

Warning

Cells have various properties like value, font, color, etc., but only some of them are returned by default, to make the result more compact and faster: VALUE, FORMATTED_VALUE and CELL_ORDINAL. You can verify this by double-clicking on any cell with the value in the result of an MDX query in SQL Server Management Studio.

Other properties, FORE_COLOR and BACK_COLOR, can be retrieved on demand, using the CELL PROPERTIES MDX keyword, an optional part of the query. When that keyword is used, only the explicitly stated properties are returned. In other words, if we want to include the color properties, we should specify those default properties explicitly or they won't be included in the result.

The success of this recipe ultimately depends on the SSAS front end you're using and its way of displaying values. It may be that in its default mode the front end omits cell properties in order to display results faster. If so, be sure to check whether there's an option in the program's connection or display properties which can turn them on when requested. If not, see if you can edit the MDX and insert the FORE_COLOR and the BACK_COLOR keywords in the CELL PROPERTIES part of the query. If that part is not there at all, you must add it at the end of the query by specifying the CELL PROPERTIES keyword and then enlisting all the properties you want to be returned. The complete list of cell properties can be found here: http://tinyurl.com/CellProperties

 

Setting default member of a hierarchy in MDX script

Setting a default member is a tempting option which looks like it can be used on any dimension we would like. The truth is far from that. Default members should be used as exceptions and not as a general rule when designing dimensions.

The reason for that is not so obvious. The feature looks self-explanatory and it's hard to anticipate what could go wrong. If we're not careful enough, our calculations can become unpredictable, especially on complex dimensions with many relations among attributes.

Default members can be defined in three places. The easy-to-find option is the dimension itself, using the DefaultMember property found on every attribute. The second option is the role, on Dimension Data tab. Finally, default members can be defined in MDX script. One of the main benefits of this place is easy maintenance of all default members in the cube because everything is in one place and in the form of an easy-to-read text. That is also the only way to define the default member of a role-playing dimension.

In this recipe we'll show the most common option, that is, the last one or how to set a default member of a hierarchy in MDX script. More information on setting the DefaultMember is available here:
http://tinyurl.com/DefaultMember

Getting ready

Follow these steps to set up the environment for this recipe:

  1. Start SSMS and connect to your SSAS 2008 R2 instance.
  2. Click on the New Query button and check that the target database is Adventure Works DW 2008R2. Then execute the following query:

    WITH
    MEMBER [Measures].[Default account] AS
    [Account].[Accounts].DefaultMember.Name
    SELECT
    { [Measures].[Amount],
    [Measures].[Default account] } ON 0
    FROM
    [Adventure Works]

  3. The results will show that the default member is Net Income account and its value in this context is a bit more than 12.6 million USD.
  4. Next, open Adventure Works DW 2008 solution in BIDS.
  5. Double-click on the Adventure Works cube and go to the Calculations tab. Choose Script View.
  6. Position the cursor at the beginning of the script, just below the CALCULATE command.

How to do it...

Follow these steps to set a new default member:

  1. Enter the following expression to set a new default account:

    ALTER CUBE CurrentCube
    UPDATE DIMENSION [Account].[Accounts],
    Default_Member = [Account].[Accounts].&[48];
    //Operating Profit

  2. Save and deploy (or just press the Deploy MDX Script icon if you're using BIDS Helper).
  3. Run the previous query again.
  4. Notice the result has changed. The new default account is Operating Profit, the one we specified in the MDX script using ALTER CUBE command. The value changed as well – now it's above 16.7 million USD.

How it works...

The ALTER CUBE statement changes the default member of a hierarchy specified in the UPDATE DIMENSION part of the statement. The third part is where we specify which member should be the default member of that hierarchy.

Don't mind that it says "UPDATE DIMENSION". SSAS 2005 and above interpret that as hierarchy.

There's more...

Setting the default member on a dimension with multiple hierarchies can lead to unexpected results. Due to attribute relations, related attributes are implicitly set to corresponding members while the non-related attributes remain on their default members, that is, the All member (also known as the root member). Certain combinations of members from all available hierarchies can result in a non-existing coordinate. In that case, the query will return no data. Other times, the intersection will only be partial. In that case, the query will return the data, but the values will not be correct which might be even worse than no data at all.

Here's an example illustrating that:

Enter the following expression in the MDX script, deploy it, and then analyze the result in the Cube Browser tab.

ALTER CUBE CurrentCube
UPDATE DIMENSION [Date].[Calendar],
Default_Member = [Date].[Calendar]
.[Calendar Year].&[2007];
-- "current" year on the user hierarchy

The expression sets the year 2007 as the default member of the [Date].[Calendar] user hierarchy.

The analysis of the Sales Amount measure in the Cube Browser shows good results in almost all cases except in few. Fiscal hierarchies that have the fiscal year level in them return empty or incomplete results when used in slicer. Empty, because the intersection between the fiscal year 2006 and the calendar year 2007 (the latter being the default member in the calendar hierarchy) is a non-existing combination. Remember, the calendar year 2007 doesn't get overwritten by the fiscal 2006. It gets combined (open the Date dimension in BIDS and observe the relations in the corresponding tab). Moreover, when you put the fiscal year 2007 in slicer, you only get a portion of data, the portion which matches the intersection of the calendar and the fiscal year. That's only one half of the fiscal year, right? In short, you have a potential problem with this approach.

Can we fix the result? Yes, we can. The correct results will be there when we explicitly select the All member from the Date.Calendar hierarchy in the slicer. Only then we get good results using fiscal hierarchies. The question is – will the end-users remember that every time?

The situation is similar when the default member is defined on an attribute hierarchy, for example, on the Date.Calendar Year hierarchy. By now, you should be able to modify the previous expression so that it sets the year 2007 as the default member on the [Date].[Calendar Year]. Test this to see it for yourself.

Another scenario could be that you want to put the current date as the default member on the Date.Date hierarchy. Try that too, and see that when you use the year 2006 from the Date.Calendar Year hierarchy in slicer, you get an empty result. Again, the intersection formed a non-existing coordinate.

To conclude, you should avoid defining default members on complex dimensions. Define them where it is appropriate: on dimensions with a single non-aggregatable attribute (that is when you set the IsAggregatable property of an attribute to False) or on dimensions with one or more user hierarchies where that non-aggregatable attribute is the top level on each user hierarchy and where all relations are well made.

The Account dimension used in this example is not such a dimension. In order to correct it, two visible attributes should be made hidden because they can cause empty results when used in slicer. Experimenting with scope might help too, but that adds to the complexity of the solution and hence the initial advice of keeping things simple when using default members should prevail.

Take a look at other dimensions in the Adventure Works DW 2008 database. There you will find good examples of using default members.

Helpful tips

When you're defining the default members in MDX script, do it in the beginning of the script. This way the calculations that follow can reference them.

In addition, provide a comment explaining which member was chosen to be the default member and optionally why. Look back at the code in this recipe to see how it was done.

Summary

In this article we discussed the common MDX tasks and one or more ways to solve them or deal with them appropriately. We took a look at the basic principles and approaches such as how to skip an axis and prevent common errors, how to set the default member of a hierarchy, and how to format cell foreground and background colors based on the value in cells.


Further resources on this subject:


About the Author :


Tomislav Piasevoli

Tomislav Piasevoli (tomislav@piasevoli.com) is a Business Intelligence Specialist with years of experience in Microsoft SQL Server Analysis Services (SSAS). He lives in Croatia and works for SoftPro Tetral d.o.o., a company specializing in development of SSAS frontends and implementation of BI solutions.

His main interests are dimensional modeling, cube design, and MDX about which he blogs at http://tomislav.piasevoli.com. Tomislav also writes articles and speaks at regional conferences and user groups. For his contribution to the community, Microsoft awarded him with the Microsoft SQL Server MVP title.

Books From Packt


Microsoft SQL Server 2008 R2 Master Data Services
Microsoft SQL Server 2008 R2 Master Data Services

Microsoft SQL Azure Enterprise Application Development
Microsoft SQL Azure Enterprise Application Development

Microsoft SQL Server 2008 R2 Administration Cookbook
Microsoft SQL Server 2008 R2 Administration Cookbook

Microsoft SQL Server 2008 High Availability
Microsoft SQL Server 2008 High Availability

Microsoft Data Protection Manager 2010
Microsoft Data Protection Manager 2010

Microsoft Visual Studio LightSwitch Business Application Development
Microsoft Visual Studio LightSwitch Business Application Development

Microsoft Silverlight 4 Data and Services Cookbook
Microsoft Silverlight 4 Data and Services Cookbook

Microsoft Dynamics AX 2009 Administration
Microsoft Dynamics AX 2009 Administration


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software