{"id":511,"date":"2019-03-01T11:20:19","date_gmt":"2019-03-01T11:20:19","guid":{"rendered":"https:\/\/int64software.com\/blog\/?p=511"},"modified":"2019-03-01T11:20:21","modified_gmt":"2019-03-01T11:20:21","slug":"handling-hierarchical-data-structures-in-sql-server","status":"publish","type":"post","link":"https:\/\/int64software.com\/blog\/2019\/03\/01\/handling-hierarchical-data-structures-in-sql-server\/","title":{"rendered":"Handling Hierarchical Data Structures in SQL Server"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Databases provide a great way to store and query large amounts of data quickly and efficiently. But what if you want to store something like a file system, where hierarchical links between the data are key?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this article I&#8217;ll be looking at how to store and query data in SQL Server in such a way that using it hierarchically is simple.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is specifically written for SQL Server, but the core functionality (CTEs) should work in many other SQL flavours including MySQL 8 and SQLite<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Data Structure<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For this example, I&#8217;ve constructed a very simple table &#8220;folder&#8221; as shown below.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"295\" height=\"283\" src=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/folder_table.png\" alt=\"Example Table &quot;folder&quot;\" class=\"wp-image-515\"\/><figcaption>Example Table &#8220;folder&#8221;<\/figcaption><\/figure><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CREATE TABLE folder (\n\tfolderid INT IDENTITY(1,1) PRIMARY KEY,\n\tparentid INT NULL,\n\tname VARCHAR(200) NOT NULL,\n\tcreated DATETIME NOT NULL DEFAULT(GETDATE()),\n\tlastupdate DATETIME NOT NULL DEFAULT(GETDATE()),\n\tFOREIGN KEY (parentid) REFERENCES folder(folderid)\n\t);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The properties of this table are:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The table has a integer primary key &#8220;folderid&#8221; which, in this case, is auto-incrementing. <\/li><li>It also has a foreign key &#8220;parentid&#8221; which may be NULL, indicating it has no parent and is thus a &#8220;root&#8221; folder, or an integer value referencing another row in the folder table by its primary key.<\/li><li>Each folder has a name to more easily identify it, and created and last update datetime values for flavour.<\/li><\/ol>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Example Data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For this example, I&#8217;ve added a series of rows to the table to show it working.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"490\" height=\"346\" src=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_example_data.png\" alt=\"Table Example Data\" class=\"wp-image-516\" srcset=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_example_data.png 490w, https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_example_data-300x212.png 300w\" sizes=\"auto, (max-width: 490px) 100vw, 490px\" \/><figcaption>Table Example Data<\/figcaption><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve tried to name the child folders in such a way that it is easy to see its intended path quickly and easily. &#8220;<em>Child 1-2<\/em>&#8221; for example is the second child of &#8220;<em>Child 1<\/em>&#8220;, which in turn is the first child of the root folder &#8220;<em>Root Folder 1<\/em>&#8220;.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Querying the Data<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">The Problem<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The data as it&#8217;s shown in the above Table Example Data screenshot is the result of a straight SELECT statement. It shows all of the data correctly, and would be fine if you are looking to get ALL of the data simply.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, consider the scenario where you only want the folder &#8220;Child 1&#8221; and its descendents. I can get &#8220;Child 1&#8221; itself easy enough with a basic SELECT:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">SELECT folderid, parentid, name \nFROM folder \nWHERE folderid = 2;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I can also get its children with a similarly simple query. But what about its children&#8217;s children, or its children&#8217;s children&#8217;s children? And I want it all in one neat query with the results properly sorted. Time to introduce the Common Table Expression.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Common Table Expressions (CTE)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A CTE is used to create a temporary results set for the lifetime of one SELECT (or INSERT, UPDATE, DELETE or MERGE) statement, so like a temporary table. Where CTEs get their real power though is that they can be self-referential and recursive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What that means in our scenario is that we can use a CTE to build a result set based on a recursive query, or automatically drill down into a hierarchical structure parent to child in a single query.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CTEs are defined with the &#8220;WITH&#8221; command, followed by a single SELECT (in this example) statement, such as:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">WITH cte_name AS ( SELECT folderid, parentid FROM folder )\nSELECT *\nFROM cte_name;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This simple example creates a CTE named &#8220;<em>cte_name<\/em>&#8221; and fills it with <em>folderid <\/em>and <em>parentid <\/em>from the <em>folder <\/em>table, and then selects the results of that. A fairly pointless example, but it shows the syntax so we can move on to something more complicated.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Get Folder Structure<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s look at our scenario again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We want to be able to query the &#8220;folder&#8221; table to find one particular folder row and all of its descendents.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\nUsing a Recursive Common Table Expression (CTE) to retrieve\na hierarchical list of child folders starting from a source \ncontainer given by @sourceid.\n*\/\nDECLARE @sourceid INT = 2;\n\nWITH cte (folderid, parentid, name, created, lastupdate, level, path) AS (\n    SELECT folderid, parentid, name, created, lastupdate, \n           0 AS level, CAST(name AS VARCHAR(1000)) AS path\n    FROM folder \n    WHERE folderid = @sourceid \n    UNION ALL \n    SELECT c.folderid, c.parentid, c.name, c.created, c.lastupdate, \n           cte.level + 1 AS level, \n           CAST((cte.path + '\/' + c.name) AS VARCHAR(1000)) AS path\n    FROM folder c \n    INNER JOIN cte ON cte.folderid = c.parentid \n) \nSELECT folderid, parentid, name, created, lastupdate, level, path\nFROM cte\nORDER BY path ASC<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It may seem daunting at first, but this is really very simple. It will first retrieve the row with folderid matching the &#8220;@sourceid&#8221; variable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It then performs a UNION to also select the children of the data in the CTE recursively, building the hierarchical tree of data. Note that the second SELECT statement performs an INNER JOIN on the CTE itself, linking the current result&#8217;s &#8220;<em>parentid<\/em>&#8221; field to the CTE result&#8217;s &#8220;<em>folderid<\/em>&#8220;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"670\" height=\"162\" src=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_1_results.png\" alt=\"Get Folder Structure Results\" class=\"wp-image-518\" srcset=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_1_results.png 670w, https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_1_results-300x73.png 300w\" sizes=\"auto, (max-width: 670px) 100vw, 670px\" \/><figcaption>Get Folder Structure Results<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here you can see we also used the CTE&#8217;s SELECT statements to inject two additional useful fields into the data: &#8220;level&#8221; and &#8220;path&#8221;.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The &#8220;level&#8221; field is set to &#8220;0&#8221; in the first SELECT as the source query, then during recursion on the second SELECT, 1 is added to the value at each depth. This allows you to quickly see how far down the hierarchy the row is. Folder with ID 15, for example, &#8220;Child-1-1-1&#8221; , has a level of 2 meaning it is the  is the child of the child of the @sourceid.<\/li><li>The &#8220;path&#8221; field is a concatenation of the name of each folder at each level with a &#8220;\/&#8221; character between them, constructing something like a file path. The final SELECT then uses this path to sort the results so that we get an easy to parse list of results<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Get Reverse Tree Branch<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As an additional step, we can reverse this procedure.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider the slightly different scenario where you instead have the ID of a child folder, and want to get a list of all of its parents right up to the root.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\nUsing a Recursive Common Table Expression (CTE) to retrieve\na hierarchical folder list starting from a child container\ngiven by @childid and navigating up to the root.\n*\/\nDECLARE @childid INT = 13;\n\nWITH cte(folderid, parentid, name, created, lastupdate, level) AS \n( \n\tSELECT folderid, parentid, name, created, lastupdate, \n               0 AS level\n\tFROM folder \n\tWHERE folderid = @childid \n\tUNION ALL \n\tSELECT c.folderid, c.parentid, c.name, c.created, c.lastupdate, \n               cte.level + 1 AS level\n\tFROM folder c \n\tINNER JOIN cte ON cte.parentid = c.folderid\n) \t\t\nSELECT folderid, parentid, name, created, lastupdate, level\nFROM cte\nORDER BY level ASC<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The primary difference here is that during the recusive SELECT statement (the second one), it is the CTE&#8217;s &#8220;<em>parentid<\/em>&#8221; field which is linked to the current folder&#8217;s &#8220;<em>folderid<\/em>&#8220;, essentially reversing the direction of traversal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also note that, because we&#8217;re working backwards up the tree, the &#8220;<em>path<\/em>&#8221; field&#8217;s construction is not as simple so has been excluded.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"538\" height=\"91\" src=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_2_results.png\" alt=\"Get Reverse Tree Branch Results\" class=\"wp-image-519\" srcset=\"https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_2_results.png 538w, https:\/\/int64software.com\/blog\/wp-content\/uploads\/2019\/03\/cte_query_2_results-300x51.png 300w\" sizes=\"auto, (max-width: 538px) 100vw, 538px\" \/><figcaption>Get Reverse Tree Branch Results<\/figcaption><\/figure>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This article shows a couple of quick and simple uses of Common Table Expressions for the purposes of building hierarchical data structures, but this only scratches the surface of what is possible with them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let me know on Twitter (<a rel=\"noreferrer noopener\" aria-label=\"@matt_is_ready (opens in a new tab)\" href=\"https:\/\/twitter.com\/matt_is_ready\" target=\"_blank\">@matt_is_ready<\/a>) if you&#8217;ve found other creative uses.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Databases provide a great way to store and query large amounts of data quickly and efficiently. But what if you want to store something like a file system, where hierarchical links between the data are key?<\/p>\n","protected":false},"author":1,"featured_media":521,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[104,7],"tags":[106,107,74,72,105,108,8],"class_list":["post-511","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sql","category-tutorial","tag-common-table-expressions","tag-cte","tag-mysql","tag-sql","tag-sql-server","tag-sqlite","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/posts\/511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/comments?post=511"}],"version-history":[{"count":10,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/posts\/511\/revisions"}],"predecessor-version":[{"id":526,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/posts\/511\/revisions\/526"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/media\/521"}],"wp:attachment":[{"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/media?parent=511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/categories?post=511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/int64software.com\/blog\/wp-json\/wp\/v2\/tags?post=511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}