September 2008 - Posts - Sparks from the Anvil

September 2008 - Posts

MDX + T-SQL: Combining relational and multi-dimensional data into one query result set

When it comes to system integration, Microsoft provides such a plethora of options it is far too easy to forget about some of them and/or think about their practical application. This is particularly true of the SQL Server BI stack which is so huge in its scope.

Our need was to populate a relational database using the results of an MDX query so we could do some data reconciliation to prove the new cube provided the results we wanted. Given my skills in C#, my immediate thought was to write a simple console application which performed an MDX query and populate a database table using SQL Bulk Insert. However, this option would not be too easy the rest of the team to support as they do not have the relevant C# skills or experience of ADOMD.NET.

Vincent Rainardi (author of Building a Data Warehouse: with examples in SQL Server) pointed me the direction of OpenQuery and linked servers. This is a remarkably simple and flexible solution to a great many system integration problems, so I thought I had better share it with a wider audience.

OpenQuery and OpenRowSet both execute pass-through queries against a specific server. The 'query string' to be executed is not evaluated by the local server but simply 'passed through' to the target server which is expected to return a row set. The 'query string' can be anything, including MDX, so long as it is understood by the target server. Well this works a treat with MDX and Analysis Services.

To use this technique, you will first need to create a linked SSAS server using either SQL Server Management Studio or in script using the stored procedure master.dbo.sp_addlinkedserver. Here is an example:

Once linked, you can then query your cube using MDX and combine the results with the content of a SQL Server table. Alternatively you can simply insert the results of the MDX query into a database table. For example, the following screenshot shows the MDX executed in SQL Server Management Studio:

Whereas the following screenshot shows the results of the equivalent OpenQuery:


Note now the column names contain the unique name of the attribute. Before showing how to deal with these, let's just look one surprising element of the functionality offered by this technique.

If you use a hierarchy in your query, then you will get extra columns describing the values of each hierarchy level. For example, if we change the above query to use the [Customer].[Customer Geography] hierarchy then you get an extra column in the query results describing the [Customer].[Customer Geography].[Country] level.

This is even more dramatic when using a parent-child hierarchy; a query against the Accounts dimension will bring back all six levels.

Dealing with Attribute Unique Names

Of course, you may find the attribute unique name a little long and cumbersome to use in your T-SQL. The easiest way to remove them is to use an alias. However, you still need to type that lengthy name in the first place.

The easy way around this is to copy the query results into Excel and then obtain the column header text from there. However, by default, the copying of column headers is switched off, so you may want to switch on the "Include column headers when copying or saving results" option in SQL Server Management Studio which can be found under Tools->Options->Query Results->Results to Grid. Here is a screenshot to make it easier:

Using an Alias 

As you will know, the square bracket in T-SQL is used as a delimiter in much the same way as it is in MDX. So simply typing:

[Customer].[Customer Geography].[Country].[MEMBER_CAPTION] AS Country

will cause a "multi-part identifier could not be bound" error. To avoid this, use double quotes around the attribute unique name as follows:

"[Customer].[Customer Geography].[Country].[MEMBER_CAPTION]" AS Country,

Numerical Advantage

The problem with OpenQuery is that every column has a data type of string, including the numerical columns. This means that the data type must be changed if you want to perform numerical computations on the figures using T-SQL. So our two numerical columns need to be wrapped in CAST & CONVERT as follows:

CAST(CONVERT(float, "[Measures].[Internet Gross Profit]") AS money) AS GrossProfit

Combining multi-dimensional and relational data together

In the case where you are creating a management report that combines the profitability figures of each division with the relevant manager's comments as to why the figure have (or have not) been achieved, then the use of OpenQuery becomes invaluable. This is because the only way to handle such a situation in the cube would be to create another dimension which links at the relevant level of granularity and enable cube write-back so the manager can update dimensional properties. A lot of hassle for a few pieces of textual information!

With OpenQuery, this becomes trivial as the text can be held in a supplementary database table and combined with the results of the MDX query.

Now the problem you may have spotted is that OpenQuery returns the MEMBER_CAPTION which will probably not be sufficiently unique to match an entry in the relational database. What you really need is the MEMBER_KEY. This can be added as a column using a calculated member as follows:

WITH MEMBER [Measures].[OrganisationID] AS [Organization].[Organizations].MEMBER_KEY

As the Adventure Works database does not contain a 'comments' table, let's create one and insert some rows using the new INSERT feature in SQL Server 2008.

CREATE TABLE dbo.ManagersComments(
    OrganisationID int NOT NULL,
    [Manager's Name] nvarchar(50) NULL,
    [Manager's Comments] nvarchar(255) NULL
INSERT INTO ManagersComments(OrganisationID, [Manager's Name], [Manager's Comments])
    VALUES (6, 'John Doe', 'My team failed again. You know how it is...'),
                (5, 'John Smith', 'My team are all stars.');

So let's bring MDX and SQL data together into one query. This is best achieved with a common table expression as the layout can be far more readable:

WITH MdxQuery
    [Net Sales],
    [Cost of Sales],
    [Gross Margin],
    [Gross Margin%]
        "[Organization].[Organizations].[Organization Level 04].[MEMBER_CAPTION]" AS [Region],
        CONVERT(int, "[Measures].[OrganisationID]") AS OrganisationID,
        CAST(CONVERT(float, "[Measures].[Net Sales]") AS money) AS [Net Sales],
        --"[Measures].[Net Sales]" AS [Net Sales],
        CAST(CONVERT(float, "[Measures].[Cost of Sales]") AS money) AS [Cost of Sales],
        CAST(CONVERT(float, "[Measures].[Gross Margin]") AS money) AS [Gross Margin],
        CONVERT(decimal(4, 2), (CONVERT(decimal(19, 17), "[Measures].[Gross Margin%]") * 100)) AS [Gross Margin%]
    FROM OPENQUERY(AdvertureWorksServer,
        'WITH MEMBER [Measures].[OrganisationID] AS
        MEMBER [Measures].[Net Sales] AS
            ([Account].[Accounts].&[50], [Measures].[Amount])
        MEMBER [Measures].[Cost of Sales] AS
            ([Account].[Accounts].&[55], [Measures].[Amount])
        MEMBER [Measures].[Gross Margin] AS
            ([Account].[Accounts].&[49], [Measures].[Amount])
        MEMBER [Measures].[Gross Margin%] AS
            [Measures].[Gross Margin] / [Measures].[Net Sales]
            [Measures].[OrganisationID], [Measures].[Net Sales], [Measures].[Cost of Sales],
            [Measures].[Gross Margin], [Measures].[Gross Margin%]
        } ON 0,
        ON 1
        FROM [Finance]
        WHERE ([Date].[Fiscal].[Fiscal Quarter].&[2004]&[1])'
CombineMdxWithTable (    
    [Manager's Name],
    [Net Sales],
    [Cost of Sales],
    [Gross Margin],
    [Gross Margin%],
    [Manager's Comments]
        B.[Manager's Name],
        A.[Net Sales],
        A.[Cost of Sales],
        A.[Gross Margin],
        A.[Gross Margin%],
        B.[Manager's Comments]
FROM MdxQuery A
    LEFT JOIN dbo.ManagersComments B ON
        A.OrganisationID = B.OrganisationID
SELECT * FROM CombineMdxWithTable


Here are the results of our query:

The Big Surprise - Support for more than two axes!

What I found most surprising about the functionality offered by OpenQuery is that it will deal with extra dimensions/axes sensibly.  Of course any multi-dimensional query can always be transformed into a two-dimensional recordset; each cell simply becomes a row in the recordset, with one column for each dimension. So for example, a four dimensional MDX query returning a two measures can be easily transformed into a two dimensional recordset containing six columns. Each row represents a cell and has two numerical columns.

Of course, if you try adding more than two axes to an MDX query in SQL Server Management Studio, this is the resulting error you will see:

Results cannot be displayed for cellsets with more than two axes.

Given that OpenQuery does such a good job of flattening the resultset into two dimensions, SQL Server Management Studio could really make more of an effort!

In reality, similar results are returned by a two-dimensional MDX query where the rows axes is a CrossJoin of all the relevant dimensions. It also has the advantage that the query would be able to take advantage of the server's AutoExists performance optimization and therefore fewer rows will be returned. However, it does not sound quite so sexy as a true multi-dimensional query. Ah, well. Technology cannot always be sexy!

Posted by DrJohn with 9 comment(s)
Filed under: ,

Goodbye Vista: Installing Windows Server 2008 on a Dell XPS laptop

Vista was driving me nuts! I could not believe how slow it was. The hard disk was always thrashing, the machine ran hot and the battery life was pants. I had spent hours optimizing my environment; first deleting all the 'bloat ware' installed by Dell, then stopping every service I did not recognise and finally removing every entry I could from the start-up registry entries (i.e. HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run).

The biggest culprit for wasting system resources was Vista's SuperFetch. Which idiot thought this up?? The service reads all the files on the computer and 'analyses' what you have done before and predicts what you may need in the immediate future and then loads the application and data into memory so you get fantastic performance if, and this is a big 'if', you happen to ask for the application or data that it thinks you want. In reality, the performance of the whole PC suffers as this silly service just wastes your PC's resources doing things that you do not need. Ahhhhh! I wish I had a shotgun and a time machine to get that S.O.A.B.!

My laptop is no slouch either. A Dell XPS M1530 laptop with Intel Core 2 Duo 2.00GHz, 4GB RAM, 250GB 5,600RPM hard drive and a 256MB NVIDIA GeForce 8600M GT graphics card driving a 1680x1050 pixel TrueLife TFT. So I was particularly annoyed by the lack of performance provided by Vista. The laptop was rated as 4.9 out of 5 in Vista's own performance benchmark; 5 been the best machines that were around when they were developing Vista. Clearly they were benchmarking how much system resource they could waste rather than focus on end-user performance!

As I develop server-based applications on the SQL Server 2005 BI suite, I had installed VMWare Workstation so I could run multiple virtual machines – one for each of my client's server configurations. I find VMWare much more flexible than Virtual PC, but then again, it's not free! What seemed silly is that the Windows Server 2003 instances running inside the virtual machine seemed much faster than Vista itself, especially when copying files across the network!

When I heard the news that SQL Server 2008 had finally shipped, I decided that it was time to do something radical: upgrade to Windows Server 2008 as the native OS and install SQL Server 2008! As a consultant on the road, I cannot afford to be without my machine for too long, so I decided the safest option would be to buy another hard drive and take the Vista disk out and replace it with a shiny new 7,200RPM hard drive. Well performance is everything!

Before taking the Vista hard drive out, I created backups onto my NAS drive and also copied onto a memory stick all the device drivers that Dell had kindly created in the c:\drivers folder (after checking they were the latest versions of course!).

The installation of Windows Server 2008 on my laptop went like a dream. Every time the OS found a new device, I simply pointed it at the root of the memory stick and, bingo, it installed without a glitch. The only devices that failed were the ones that Dell had forgotten to place in the c:\drivers folder or for my own printer/scanner. These were soon downloaded from Dell and Canon's web sites.

Why did it go so smoothly? Well Windows Server 2008 shares the same kernel as Vista and the device driver model is the same. So a Vista device driver will work with Windows Server 2008 and visa versa. However, be aware that this will only work with the 32-bit version of Windows Server 2008 as very few device drivers are available for 64-bit Windows.

A very Desktop Experience

Of course Vista does have some charms and I soon came to miss certain applications like Windows Photo Gallery and Windows Media Player. I tried finding them on the Microsoft Download site but to no avail. Windows Media Player is built into Vista and therefore not provided as a separate download. I searched the internet for clues as to where I could get them from, but to no avail. Several days went by before I found which has many tips on how to turn Windows Server 2008 into a workstation. This includes how to turn on something called the Desktop Experience. I followed the procedure and my desired applications magically appeared. However, some undesirable applications also popped up like Windows Defender (what junk!), Windows Mail, Windows Contacts and Windows Calendar. Unfortunately, you get all or nothing. There is no fine control over which of the Vista applications get installed. At least you can disable Windows Defender by disabling the related service.

Virtual CD-ROM

Eager to install SQL Server 2008 from a freshly downloaded ISO image, I started scouting for a way to load an ISO images as a virtual drive. I figured there must be a way to load an ISO image built into the OS itself. However, I could not find the right command-line, but I am sure there is someone out there that knows how to do it! So I tried my old favourite Virtual CD-ROM Control Panel which is a free download originally developed by Microsoft but now provided as an unsupported utility. To my surprise this worked a treat. Amazing since it was last updated in 2006!

Burning Desire

Over the years I have been a great lover of Nero Burning ROM. The main application had a simple but powerful user interface. However, the Nero package has grown out of all recognition over the years and offers so many utilities to do things I never imagined I needed (i.e. bloat ware) that I refuse to install it on my machine. Unfortunately the original Nero Burning ROM cannot be purchased separately, so I needed an alternative. After a perusal of Wikipedia, I found some freeware called ImgBurn. The UI is almost identical to Nero Burning ROM and seems to work well.

Well Connected

One slightly problematic device I had was my 3 USB mobile internet modem. This worked fine on first installation then stopped working for no apparent reason. I figured out it may be something to do with the Windows Firewall which, if I remember correctly, first appeared when I switched on the Desktop Experience. However, after tinkering with the firewall settings the device would still not work. I tried installing the latest device drivers, but to no avail. I uninstalled the device software and decided to ring 3's support line, confident in the knowledge that they would be no help at all; after all how many customers have mobile internet installed on a server?? Of course, several days passed before I resolved to get the problem fixed. Just prior to the call I thought I would prepare by reinstalling the device so the details of the problem would be fresh in my mind. Well blow me, the damn thing started working!

Mouse Problems

The one device that I have real problems with is my Logitech V470 Cordless Laser Mouse for Bluetooth. I can add it as a Bluetooth device, but it will not actually work. If I install the latest SetPoint software from Logitech, the mouse pointer jumps all over the place like a demented wasp. Ideas anyone?

My tool bag

I often find it useful to know what other consultants in the field carry around in their 'tool bag'. Well, here is my set of applications currently installed on the laptop:

  • Microsoft Windows Server 2008 including IIS 7.0
  • Microsoft SQL Server 2008 Developer Edition including SSAS, SSRS and SSIS and the new Adventure Works 2008 database samples.
  • Microsoft Visual Studio 2008
  • MSDN Library
  • Microsoft Office 2007 with "Save as PDF" enhancement
  • Microsoft Data Mining Add-ins for Excel 2007
  • UltraEdit – fantastic text and code editor I have been using for many, many years
  • Password Safe – I use this freeware to hold the username/password to over 100 web sites and bank accounts. They are all safe inside a heavily encrypted file which can be safely backed up to my NAS drive or memory stick without any danger of someone else been able to open the file.
  • PowerMarks – the easy way to move your internet favourites from machine to machine
  • Adobe Acrobat Reader – of course!
  • Primo PDF – freeware alternative to Adobe Acrobat Distiller for creating PDF files
  • Paint.NET – what a great free alternative to Adobe Photoshop Elements
  • Ultratagger – easy to use MP3 tagging software
  • FileZilla – great freeware FTP application
  • WinZip – the de facto standard
  • Apple iTunes for my iPod and (future) iPhone
  • ImgBurn DVD/CD-ROM burning software
  • 3 USB mobile internet

So if you are thinking of making the move from Vista to Windows Server 2008, do it now! The stability, performance, flexibility and power of Windows Server 2008 can be yours.

Good luck!


Updated: 9-Apr-2009

Going 64-bit

If you are thinking of making the switch to 64-bit, then do it!  Originally, I only had the option of 32-bit drivers from Dell.  So as soon as I found out that 64-bit drivers were available, I did the upgrade.  Everything went even more smoothly than the original conversion, so I was very impressed.  See comment below for more info.

Posted by DrJohn with 4 comment(s)

Busting for a Wii at SQL Bits

"I'm busting for a Wii!" was my wife's exclamation in the centre of Warrington. We had been an attempting to avoid traffic on the M6 but got snarled up in even more traffic in central Warrington. I did not understand at first, but then I saw the cheeky kid's grin on the advert on the back of a bus. In good northern dialect, he was not just bursting, but "busting" with excitement about the latest Nintendo games machine. What surprised me more was what followed. My wife gave me a 30 minute rant questioning exactly why I had not yet brought her a games machine. Of course my teenage daughter joined in the fray whilst my teenage son remained quite. Games machines have long been the domain of spotty teenage boys or young men with time on their hands and few friends. They are certainly not the domain of middle age females with a technology adversion! So I was rather taken aback by the whole situation.

However, this weekend the SQL Bits conferance delivered in more ways than I could possibly imagine. The event was well organised and well attended and all the lectures on the "track" I was on were well presented.

Andrew Sadler (formerly of ProClarity and now a consultant with Edenbrook) did a breakneck demonstration of the Microsoft BI stack including PerformancePoint and Excel Services. As I work with this stuff every day, I did not learn anything particularly new; it is just great to see someone else's take of the Microsoft offerings and exactly how they present it all as a 'coherent' strategy. There was clearly pent up frustration in the audience that the ProClarity product had been left on the shelf by Microsoft. A great tool been suffocated by the giant. I just hope that PerformancePoint v2 (whenever it surfaces) actually provides functionality as good, or better, than ProClarity's.

Simon Sabin did a great job of introducing some of the new features in the T-SQL language. To be honest, the audience got most animated when they realised Simon had simply highlighted the name of a table and hit some key and SQL Server Management Studio performed a query that listed not only the table definition but primary keys etc. He then showed us all how to configure keyboard shortcuts in Tools->Options->Environment->Keyboard. It seems that any single parameter stored proc (including your own) can be mapped to a keyboard shortcut and it will be passed the highlighted text when invoked. Simple, effective and one of the best things I learnt out of the session! Not that I am decrying Simon's excellent session, but something simple like a keyboard shortcut can save a lot of time in the long run, and these things are invaluable.

Allan Mitchell performed a great demo of the Data Mining Add-In for Excel. This is a tool that I always keep meaning to use on a project, but somehow never get around to getting it out of the bag and dusting it off. The new version of the DM Add-In for Excel 2007 demos really well. I will have to make a determined effort to do something with this technology soon!

It was great to meet Chris Webb for the first time. Having read the blogs and the book, it was good to get to know the guy in person. I will be using Intelligencia Query for BIDS and Reporting Services in my next project jointly developed by Chris and Andrew Wiles who also presented his 'reusable' approach to BI the day. Colin Hardie of the IMGroup ably demonstrated the new MERGE feature in T-SQL as well as several other approaches to handling Type 2 slowly changing dimensions.

It was great to meet old friends, put faces to people I had only previously met in 'cyberspace' and meet some new contacts. Microsoft provided free drinks after the gig and, even better, I won a Wii in the RedGate prize draw. Even my wife agrees that it was a good conference!

Posted by DrJohn with no comments
Filed under: