Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Here are some notes on "SQL Server 2008 Hierarchies and HierarchyID" I took while attending an advanced class on SQL Server taught by Paul Nielsen (from https://www.sqlserverbible.com).
Please note that, although these notes were taken during the class, I might have added some of my own (mis)interpretation :-). Always check your facts on Books Online (I try to provide links when applicable). As with anything else you get from a blog, never use any of this in production before you thoroughly validate it a test environment. Please keep in mind that some of those will be hard to follow without some pre-requisite knowledge and the right context. Reading the post from top to bottom will help.
Hierarchies
- Use cases: Hierarchy, graphs (many to many), XML indexing
- Adjacency Lists: Species trees, directory folders, simple org charts
- Dual parent adjacency list: Genealogies
- Multiple Cardinality: Bill of materials, complex org charts
- See https://technet.microsoft.com/en-us/library/bb677290.aspx
Adjacency pairs
- Case: ManagerID in person table (AdventureWorks, 2005 or earlier)
- Usually implemented as column pointing to PK on same table
- Easy to find one level up or down, easy to reparent (replace manager)
- Can leverage Recursive CTEs, user-defined functions
Bill of Materials
- Case: Keeping track of all parts, subparts required to build a device
- Case: Classes are pre-requisites to multiple other classes
- m:m adjacency pairs
- Typically implemented as an associative table
- Can leverage user-defined functions
Materialized Path
- Absolute path for row stored in database
- Usually implemented as a text column in the table, using some sort of delimiter.
- Example: 1 - 1.1 - 1.1.1 - 1.1.2 - 1.2 - 1.3 - 1.3.1
- Example: /A - /B - /B/C - /B/D - /B/D/E - /B/D/F - /G
- Easy to store as primary key, search all levels, difficult to reparent, fast queries
- User-defined function to calculate materialized path (could be used in index)
- You could also have the parent ID in parallel (use both at once)
HierarchyID
- Like a materialized path: easy to search all levels, difficult to reparent
- Easier to use as compound key
- Example: /1/ - /1/1/ - /1/1/1/ - /1/2/
- Compact design: CLR Data Type (SQLTypes library – SQLHierarchyID)
- Used by SQL Server 2008 in the “hid” field in XML Indexing
- See https://msdn.microsoft.com/en-us/magazine/cc794278.aspx
HierarchyID - Methods
- GetRoot, GetAncestor, GetDescendant
- GetLevel, IsDescendantOf, GetReparentedValue
- ToString, Parse, Read, Write
- See https://msdn.microsoft.com/en-us/library/bb677193.aspx
HierarchyID – Indexing
- Index by Node – Index on (HierarchyID)
- Index by Level – Index on (Level[persisted], HierarchyID)
Hierarchy – Demo – Adjacency Pairs
- Putting ManagerID back in AdventureWorks2008
- OrganizationNode is HierarchyID in HumanResources.Employee table
- Self-join on M.OrganizationNode = E.OrganizationNode.GetAncestor(1)
- See https://sqlblog.com/blogs/paul_nielsen/archive/2008/10/03/recursive-ctes-in-adventureworks-2008.aspx
- Watching out for runaway loops (similar to deadlock detection).
Hierarchy – Demo – Materialized Path
- Creating a column, storing the hierarchy
- Querying in multiple ways, using functions
- Storing the Level in an index, querying by level
Hierarchy – Demo – HierachyID
- Using AdventureWorks2008, which uses OrganizationalNode, which is a HierarchyID
- Looking at it as binary, .ToString.
- Querying based on a string (no need to convert to binary)
- Query a node to @Manager, querying all nodes under @Manager using .IsDescendentOf
- How to insert – Use HierarchyID::GetRoot() or manager.GetDescendant(...)
Read more at https://technet.microsoft.com/en-us/library/cc721270.aspx
(includes other topics, search for HierarchyID)