Home > SQL Server Tips > Data Warehousing and Business Intelligence > Parent-child dimensions in SQL Server 2005 with Analysis Services MDX
SQL Server Tips:
EMAIL THIS
 TIPS & NEWSLETTERS TOPICS 

DATA WAREHOUSING AND BUSINESS INTELLIGENCE

Parent-child dimensions in SQL Server 2005 with Analysis Services MDX


Baya Pavliashvili
09.23.2008
Rating: -4.80- (out of 5)


Expert advice on database administration
Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us    Add to Google


Parent-child dimensions in SQL Server 2005 solve the common business problem of defining records in a particular table related to other records within the same table. For example, each employee has a direct supervisor, who in turn has her own supervisor, all the way up to the enterprise owner or the chief executive officer.
More on Analysis Services and hierarchy dimensions:
  • How to use SQL Server 2008 hierarchyid data type
  • Tutorial: SQL Server 2005 Analysis Services
  • How to use the LEFT vs. RIGHT OUTER JOIN in SQL
  • Similarly, if your business serves institutional customers, then each entity could be a "child" of another larger organization or division. So the smallest customer could be a sub-department, which rolls up to a department, group, market, region, division and finally the full organization.

    Your reports and analytical views will often need to group such related records together. A common example would be to examine the manager's sales along with the sales of all employees who work for this manager.

    Handling such recursive relationships in SQL can be tricky because each record can have a different number of parent records. Sometimes this condition is referred to as unbalanced or ragged hierarchy. For example, let's review a very small "employees" table:

    CREATE TABLE [dbo].[Employees](
    [EmployeeID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](20) NOT NULL,
    [Title] [nvarchar](30) NULL,
    [ReportsTo] [int] NULL
    CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED
    (
    [EmployeeID] ASC
    )
    )
    ALTER TABLE [dbo].[Employees] ADD
    CONSTRAINT [FK_Employees_Employees1] FOREIGN KEY([ReportsTo])
    REFERENCES [dbo].[Employees] ([EmployeeID])

    Let's say we only have four records in this table, as follows:

    Employee ID Name Title Reports To
    2 Andrew President, Sales NULL
    3 Janet sr. sales rep 2
    4 Margaret sales rep 3
    5 Steven Intern 4

    In this fictitious organization, Andrew is the "big dog" and his record has no parent because he doesn't have a direct supervisor. Janet's record has one parent, Margaret's record has two and Steven's has three.

    How would you retrieve an organizational chart from your employee table? Let's say we want to retrieve records for Steven and his immediate supervisor. That's relatively easy:

    SELECT
    a.EmployeeID,
    a.Name,
    a.Title,
    b.Name AS SupervisorName,
    a.ReportsTo
    FROM Employees a
    LEFT JOIN Employees b ON a.ReportsTo = b.EmployeeID
    WHERE a.EmployeeID = 5

    But this only gives us Steven and Margaret. To get the next person in the hierarchy, we'd have to join the Employees table to itself, twice. To get the full hierarchy we'd need three joins, like the following:

    SELECT a.EmployeeID,
    a.Name,
    a.Title,
    b.Name AS SupervisorName,
    c.Name AS NextSupervisorName,
    d.Name AS TopSupervisorName
    FROM Employees a
    LEFT JOIN Employees b ON a.ReportsTo = b.EmployeeID
    LEFT JOIN Employees c ON b.ReportsTo = c.EmployeeID
    LEFT JOIN Employees d ON c.ReportsTo = d.EmployeeID
    WHERE a.EmployeeID = 5

    Result:

    EmployeeID Name Title Supervisor NextSupervisor TopSupervisor
    5 Steven Intern Margaret Janet Andrew

    This works OK on a fictitious company sample with a handful of employees, but it should be apparent that retrieving a hierarchy with recursive relationships with SQL can get difficult to manage very quickly. The query becomes even more cumbersome if we want to retrieve the sales of Steven along with each of his manager's sales. For each manager, we should include her sales along with sales of her subordinates:

    SELECT
    (SELECT COUNT(*) FROM employees a1
    INNER JOIN orders b ON a1.employeeid = b.employeeid
    WHERE a1.employeeid = a.employeeid) AS [steven's sales],
    (SELECT COUNT(*) FROM employees a1
    INNER JOIN orders b ON a1.employeeid = b.employeeid
    WHERE a1.employeeid = a2.employeeid
    OR a1.employeeid = a.employeeid) AS [margaret's sales],
    (SELECT COUNT(*) FROM employees a1
    INNER JOIN orders b ON a1.employeeid = b.employeeid
    WHERE a1.employeeid = a3.employeeid
    OR a1.employeeid = a.employeeid
    OR a1.employeeid = a2.employeeid
    OR a1.employeeid = a3.employeeid) AS [janet's sales],
    (SELECT COUNT(*) FROM employees a1
    INNER JOIN orders b ON a1.employeeid = b.employeeid
    WHERE a1.employeeid = a4.employeeid
    OR a1.employeeid = a.employeeid
    OR a1.employeeid = a2.employeeid
    OR a1.employeeid = a3.employeeid
    OR a1.employeeid = a4.employeeid) AS [andrew's sales]
    FROM employees a INNER JOIN employees a2
    ON a.reportsto = a2.employeeid
    INNER JOIN employees a3 ON a2.reportsto=a3.employeeid
    INNER JOIN employees a4 ON a3.reportsto=a4.employeeid
    WHERE a.employeeid = 5

    Result:

    Steven's sales Margaret's sales Janet's sales Andrew's sales
    42 198 325 421

    You can easily implement this type of relationship with a parent-child dimension using Analysis Services MDX.

    You don't have to make any changes to your relational table in order to create a parent-child dimension. Simply follow the dimension wizard screens, much like designing any other regular dimension. The wizard automatically detects the recursive relationship if you have specified primary key and foreign key constraints within your relational dimension. Alternatively you could also define logical relationships within your data source view.

    In our example, the column "ReportsTo" references the "EmployeeID" column. Once you have created a parent-child dimension, you should set the MembersWithData property of your attribute hierarchy to NonLeafDataHidden. This property determines whether to display non-leaf (meaning members not on the bottom level of the parent-child hierarchy) attribute members. By default the parent-child hierarchy is given the same name as the dimension table. I renamed the hierarchy to "org_chart" for clarity.

    Once you process your dimension, the employees will show up as follows (Figure 1):

    image of parent-child hierarchy dimensions using SQL Server Analysis Services MDX


    Figure 1: Hierarchy results after processing dimensions in Analysis Services MDX.

    If you had left MembersWithData at its default value (NonLeafDataVisible), you'd see the values of Andrew under Andrew, Janet under Janet and so on. Indeed, if you wanted to see Andrew's orders without adding orders of his subordinate employees to his total you would choose NonLeafDataVisible.

    With MDX, getting the organizational structure starting from Steven involves executing a very simple query, as follows:

    SELECT ASCENDANTS(employees.org_chart.steven) ON 0,
    {measures.[orders count]} ON 1
    FROM [cube name]

    Results:

    Steven Margaret Janet Andrew All
    Orders Count 42 198 325 421 421

    Similarly, to retrieve all employees of Janet you could issue the following MDX query:

    SELECT
    DESCENDANTS(employees.org_chart.Janet) ON 0,
    {measures.[orders count]} ON 1
    FROM [cube name]

    Results:

    Janet Margaret Steven
    Orders Count 325 198 42

    What if you wanted to see Janet's sales excluding the sales of employees who report to her? You'd use the attribute hierarchy associated with the dimension key, as opposed to the parent-child hierarchy, as follows:

    SELECT
    employees.employees.Janet ON 0,
    {measures.[orders count]} ON 1
    FROM [cube name]

    Results:

    Janet
    Orders Count 127

    Alternatively, you could exploit DataMember function to retrieve the sales associated only with Janet while querying the parent-child hierarchy, as follows:

    SELECT
    employees.org_chart.Janet.DataMember ON 0,
    {measures.[orders count]} ON 1
    FROM [cube name]

    Parent-child dimensions can handle any number of levels, even though you only define a single level. Unlike SQL Server you don't have to worry about adding variable number of joins to your MDX statements in order to retrieve parents (or children) of a particular member.

    Parent-child hierarchy promotes members to the top level based on the value of the RootMemberIF property. In the example shown earlier in this tip, Andrew appears on the top level of the hierarchy because the value of ReportsTo column is null. Let's see what happens if we update the row for Margaret's so that employee id and reports to column have the same value, equal to 4. Now both Margaret and Andrew appear on top of the hierarchy (Figure 2).

    parent-child hierarchy relationship using SQL Server Analysis Services MDX


    Figure 2: Results after updating rows so employee id and reports to column have the same value, equal to 4.

    The default value of the RootMemberIF property is ParentIsBlankSelforMissing. This value indicates that each member whose record has NULL or blank values in the ReportsTo column, as well as those whose employee id and reports to
    Stay up-to-date with BI and Data Warehousing:
    Receive SQL Server-related news, tech tips and more delivered directly to your Inbox. Sign up for our Business Intelligence and Data Warehousing newsletter now.
    columns have identical values, will be promoted to the top level of the hierarchy. Alternatively, you could choose ParentIsBlank, ParentIsMissing or ParentIsSelf values for this property, depending on your needs.

    Another interesting property of parent-child hierarchies is NamingTemplate. In a regular hierarchy, each level is named after the attribute it is based on. For example, in a date hierarchy you would have levels of year, quarter, month, etc. Since you only define a single attribute for the parent-child hierarchy, it cannot inherit the name for various levels based on attribute names. Instead, it assigns an ordinal number to levels. By default, levels would be called Level 01, Level 02, Level 03 and so on. You can override this default behavior and provide a more descriptive naming template. For example, in our sales scenario we could call levels Salesperson01, Salesperson02, etc. To do so, set the value of NamingTemplate property to "Salesperson *".

    ABOUT THE AUTHOR:   
    Baya Pavliashvili is a database consultant helping his customers develop highly available and scalable applications with SQL Server and Analysis Services. Throughout his career he has managed database administrator teams and databases of terabyte caliber. Baya's primary areas of expertise are performance tuning, replication and data warehousing. He can be reached at baya@bayasqlconsulting.com.

    MEMBER FEEDBACK TO THIS TIP

    Do you have a comment on this tip? Let us know.


    Rate this Tip
    To rate tips, you must be a member of SearchSQLServer.com.
    Register now to start rating these tips. Log in if you are already a member.




    Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us    Add to Google


    RELATED CONTENT
    SQL Server data warehousing/business intelligence
    Tutorial: SQL Server Integration Services (SSIS) best practices
    FAQ: Troubleshooting SQL Server Reporting Services
    What's new in SQL Server 2008 Reporting Services?
    SQL Server 2008 Integration Services delivers new features
    Tips for tuning SQL Server 2005 to improve reporting performance
    Troubleshoot Web service issues in SQL Server 2005 Reporting Services
    Ordering the results of a SQL query
    Using MDX and UDM in a SQL Server Analysis Services environment
    Configuring SQL Server with a changed computer name
    SSIS error message due to installation problem on SQL Server 2005

    SQL Server 2005 (Yukon)
    Tips for tuning SQL Server 2005 to improve reporting performance
    Using DATEADD and DATEDIFF to calculate SQL Server datetime values
    SQL Server consolidation: Why it's an optimization technique
    Using SQL Server datetime functions GETDATE, DATENAME and DATEPART
    SSIS error message due to installation problem on SQL Server 2005
    SQL Server data conversions from date/time values to character types
    Basics for working with DATETIME and SMALLDATETIME in SQL Server 2005
    How to configure Database Mail in SQL Server 2005 to send mail
    How to use rank function in SQL Server 2005
    Manage traces in SQL Server 2005 Analysis Services with XMLA commands
    SQL Server 2005 (Yukon) Research

    SQL Server performance and tuning
    How to configure storage in SQL Server DB with more writes than reads
    Avoid cursors in SQL Server with these methods to loop over records
    Solve SQL Server errors and more from the DBA trenches -- part 2
    Tutorial: Learn SQL Server basics from A-Z
    FAQ: Troubleshooting SQL Server Reporting Services
    How to disable the shrink database task in SQL Server 2000 and 2005
    SQL Server out of memory: Troubleshoot and avoid SQL memory problems
    Basic objects of T-SQL in SQL Server 2008
    Using T-SQL data types in SQL Server 2008
    Additional T-SQL operations in SQL Server 2008

    RELATED GLOSSARY TERMS
    Terms from Whatis.com − the technology online dictionary
    data aggregation  (SearchSQLServer.com)
    data preprocessing  (SearchSQLServer.com)
    data warehouse  (SearchSQLServer.com)
    FileMaker  (SearchSQLServer.com)
    GIS  (SearchSQLServer.com)
    MOLAP  (SearchSQLServer.com)
    pivot table  (SearchSQLServer.com)
    Quiz: SQL Server 2000  (SearchSQLServer.com)
    SQL  (SearchSQLServer.com)
    T-SQL  (SearchSQLServer.com)

    RELATED RESOURCES
    2020software.com, trial software downloads for accounting software, ERP software, CRM software and business software systems
    Search Bitpipe.com for the latest white papers and business webcasts
    Whatis.com, the online computer dictionary

    DISCLAIMER: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.



    SQL Server Development - .NET, C#, T-SQL, Visual Basic
    HomeNewsTopicsITKnowledge ExchangeTipsAsk the ExpertsMultimediaWhite PapersIT Downloads
    About Us  |  Contact Us  |  For Advertisers  |  For Business Partners  |  Site Index  |  RSS
    SEARCH 
    TechTarget provides enterprise IT professionals with the information they need to perform their jobs - from developing strategy, to making cost-effective IT purchase decisions and managing their organizations' IT projects - with its network of technology-specific Web sites, events and magazines.

    TechTarget Corporate Web Site  |  Media Kits  |  Reprints  |  Site Map




    All Rights Reserved, Copyright 2005 - 2008, TechTarget | Read our Privacy Policy
      TechTarget - The IT Media ROI Experts