<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Silverlight &#124; WPF &#124; Microsoft.Net &#187; reqursive-query</title>
	<atom:link href="http://joel.neubeck.net/tag/reqursive-query/feed/" rel="self" type="application/rss+xml" />
	<link>http://joel.neubeck.net</link>
	<description>Simplifing structure without changing results</description>
	<lastBuildDate>Fri, 01 Apr 2011 21:34:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Classification Table &#8211; Part 1</title>
		<link>http://joel.neubeck.net/2007/08/classification-table-part1/</link>
		<comments>http://joel.neubeck.net/2007/08/classification-table-part1/#comments</comments>
		<pubDate>Wed, 08 Aug 2007 22:21:46 +0000</pubDate>
		<dc:creator>joel</dc:creator>
				<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[CTE]]></category>
		<category><![CDATA[reqursive-query]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[table-valued]]></category>

		<guid isPermaLink="false">http://joel.neubeck.net/2007/08/classification-table-design/</guid>
		<description><![CDATA[Frequently our team is tasked with creating a way to categorize data. One very common and flexible approach is to create a table which contains a series of parent-child relationships. This hierarchical approach can be extremely flexible and efficient for categorizing multiple levels of content. Here is an example of a table used to store [...]]]></description>
			<content:encoded><![CDATA[<p>Frequently our team is tasked with creating a way to categorize data. One very common and flexible approach is to create a table which contains a series of parent-child relationships. This hierarchical approach can be extremely flexible and efficient for categorizing multiple levels of content. Here is an example of a table used to store this type of classification.</p>
<table border="1">
<tr>
<td><strong>Id</strong></td>
<td><strong>ParentId</strong></td>
<td><strong>Name</strong></td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>Attributes</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>Color</td>
</tr>
<tr>
<td>3</td>
<td>2</td>
<td>Red</td>
</tr>
<tr>
<td>4</td>
<td>2</td>
<td>Blue</td>
</tr>
<tr>
<td>5</td>
<td>2</td>
<td>Green</td>
</tr>
<tr>
<td>6</td>
<td>2</td>
<td>Purple</td>
</tr>
<tr>
<td>7</td>
<td>1</td>
<td>Font</td>
</tr>
<tr>
<td>8</td>
<td>7</td>
<td>Times New Roman</td>
</tr>
<tr>
<td>9</td>
<td>8</td>
<td>Bold</td>
</tr>
<tr>
<td>10</td>
<td>8</td>
<td>Italic</td>
</tr>
<tr>
<td>11</td>
<td>7</td>
<td>Arial</td>
</tr>
<tr>
<td>12</td>
<td>11</td>
<td>Bold</td>
</tr>
<tr>
<td>13</td>
<td>7</td>
<td>Calibri</td>
</tr>
<tr>
<td>14</td>
<td>13</td>
<td>Bold</td>
</tr>
</table>
<p>From this table we can visualize a simple nested tree of classifications</p>
<ul>
<li>Attributes
<ul>
<li>Color
<ul>
<li>Red</li>
<li>Blue</li>
<li>Green</li>
<li>Purple</li>
</ul>
</li>
</ul>
<ul>
<li>Font
<ul>
<li>Times New Roman
<ul>
<li>Bold</li>
<li>Italic</li>
</ul>
</li>
</ul>
<ul>
<li>Arial
<ul>
<li>Bold</li>
<li>Calibri</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>From a SQL perspective, interacting with this structure is quite painless. Through the use of a composite table, this structure lends itself well to having entities with multiple classification.</p>
<table border="1">
<tr>
<td><strong>ClassificationId</strong></td>
<td><strong>EntityId</strong></td>
</tr>
<tr>
<td>4</td>
<td>1</td>
</tr>
<tr>
<td>9</td>
<td>1</td>
</tr>
<tr>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td>10</td>
<td>2</td>
</tr>
</table>
<p>If a user wants entities which are classified as “Times New Roman” “Bold” they restrict the results to those with a ClassificationId = 9.</p>
<p>Now what if they want are those entities which have any of the “Font” sub classifications (ClassificationId = 7,8,9,10,11,12,13,14)?</p>
<p>This is where it gets a bit more tricky. The approach I have found most flexible is to create a custom table-valued function which recursively walks the table and returns all children of the specified parent.  The results of this reqursive query are returned in the form of a temporary named result set, known as a common table expression (CTE). If our desire was to return more than just the classifications Id we could use this CTE as a sub query on an additional query.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="t-sql" style="font-family:monospace;">ALTER FUNCTION [Resource].[ClassificationChildren]
(
 @ClassificationId int
)
RETURNS TABLE
AS
RETURN
( WITH Classes (Id, ParentId, [Level]) AS
 (
  -- Create the anchor query. This establishes the starting point
  SELECT c.[Id],c.[ParentId],0
  FROM Classification c
  WHERE c.[Id] = @CategoryId
  UNION ALL
  -- Create the recursive query. This query will be executed
  -- until it returns no more rows
  SELECT
  c.[Id],c.[ParentId], b.[Level]+1
  FROM Classification c
  INNER JOIN Classes b ON COALESCE(c.[ParentId],0) = b.[Id]
 )
SELECT k.Id FROM Classes k
)</pre></td></tr></table></div>

<p>Once I have this function, I can create a query to give me the results I desire.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="t-sql" style="font-family:monospace;">SELECT * FROM Entity LEFT JOIN 
EntryClassification ON Entity.Id = EntryClassification.EntityId
WHERE EntryClassification.ClassificationId in 
(SELECT Id FROM ClassificationChildren(7))</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://joel.neubeck.net/2007/08/classification-table-part1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

