<?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>Martin's Blog &#187; T-SQL</title>
	<atom:link href="http://www.martienus.com/tag/t-sql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.martienus.com</link>
	<description>Logic to Art</description>
	<lastBuildDate>Fri, 12 Feb 2010 19:07:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>T-SQL: Breadth-First shortest-route search</title>
		<link>http://www.martienus.com/code/t-sql-breadth-first-shortest-route-search-stored-procedure.html</link>
		<comments>http://www.martienus.com/code/t-sql-breadth-first-shortest-route-search-stored-procedure.html#comments</comments>
		<pubDate>Wed, 18 Jun 2008 19:14:00 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[Breadth-First]]></category>
		<category><![CDATA[shortest route]]></category>
		<category><![CDATA[Stored Procedure]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://www.martienus.com/?p=14</guid>
		<description><![CDATA[A while ago I came across the problem of determining the shortest route in a many-to-many self-join table. The linker table consists of two ID columns to link nodes together and is called `vertices`. This represents an unweighted and undirected node graph. In an unweighted undirected graph there can be no heuristic searching for there [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I came across the problem of determining the shortest route in a many-to-many self-join table. The linker table consists of two ID columns to link nodes together and is called `vertices`. This represents an unweighted and undirected node graph.</p>
<p>In an unweighted undirected graph there can be no heuristic searching for there is no clue (weight or direction) which possible leaf node gets you to the target quickest. Therefore an uninformed search is the only option and for this I utilized the <a href="http://en.wikipedia.org/wiki/Breadth-first_search" target="_blank">breadth-first</a> search algorithm.</p>
<p>The breadth-first algorithm visits the leafnodes per generation first and not by branch first. In practice this is the optimal method most of the time.</p>
<p>T-SQL Implementation:</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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
</pre></td><td class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">PROCEDURE</span> BFS<span style="color: #808080;">&#40;</span>
	@<span style="color: #0000FF;">FROM</span> <span style="color: #0000FF;">INT</span>,
	@<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">INT</span>
<span style="color: #808080;">&#41;</span>
<span style="color: #0000FF;">AS</span>
&nbsp;
<span style="color: #0000FF;">BEGIN</span>
	<span style="color: #0000FF;">DECLARE</span> @Nodes <span style="color: #0000FF;">TABLE</span> <span style="color: #808080;">&#40;</span>Generation <span style="color: #0000FF;">INT</span>, p <span style="color: #0000FF;">INT</span>, r <span style="color: #0000FF;">INT</span>, <span style="color: #0000FF;">UNIQUE</span><span style="color: #808080;">&#40;</span>p, r<span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span>
	<span style="color: #0000FF;">DECLARE</span> @Generation <span style="color: #0000FF;">INT</span>
&nbsp;
	<span style="color: #0000FF;">SELECT</span> @Generation <span style="color: #808080;">=</span> <span style="color: #000;">0</span>
&nbsp;
	<span style="color: #0000FF;">INSERT</span> @Nodes
		<span style="color: #808080;">&#40;</span>
			Generation,
			p
		<span style="color: #808080;">&#41;</span>
	<span style="color: #0000FF;">SELECT</span>	@Generation,
			@<span style="color: #0000FF;">FROM</span>
&nbsp;
	<span style="color: #0000FF;">WHILE</span> <span style="color: #FF00FF;">@@ROWCOUNT</span> <span style="color: #808080;">&gt;</span> <span style="color: #000;">0</span> <span style="color: #808080;">AND</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">EXISTS</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">FROM</span> @Nodes <span style="color: #0000FF;">WHERE</span> p <span style="color: #808080;">=</span> @<span style="color: #0000FF;">TO</span><span style="color: #808080;">&#41;</span>
		<span style="color: #0000FF;">BEGIN</span>
			<span style="color: #0000FF;">SELECT</span> @Generation <span style="color: #808080;">=</span> @Generation <span style="color: #808080;">+</span> <span style="color: #000;">1</span>
&nbsp;
			<span style="color: #0000FF;">INSERT</span>	@Nodes
				<span style="color: #808080;">&#40;</span>
					Generation,
					p,
					r
				<span style="color: #808080;">&#41;</span>
&nbsp;
			<span style="color: #0000FF;">SELECT</span>	@Generation,
					bid,
					aid
			<span style="color: #0000FF;">FROM</span>	vertices
			<span style="color: #0000FF;">WHERE</span>	aid <span style="color: #808080;">IN</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> p <span style="color: #0000FF;">FROM</span> @Nodes <span style="color: #0000FF;">WHERE</span> Generation <span style="color: #808080;">=</span> @Generation <span style="color: #808080;">-</span> <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>
				<span style="color: #808080;">AND</span> bid <span style="color: #808080;">NOT</span> <span style="color: #808080;">IN</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> p <span style="color: #0000FF;">FROM</span> @Nodes<span style="color: #808080;">&#41;</span>
			<span style="color: #0000FF;">UNION</span>
			<span style="color: #0000FF;">SELECT</span>	@Generation,
				aid,
				bid
			<span style="color: #0000FF;">FROM</span>	vertices
			<span style="color: #0000FF;">WHERE</span>	bid <span style="color: #808080;">IN</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> p <span style="color: #0000FF;">FROM</span> @Nodes <span style="color: #0000FF;">WHERE</span> Generation <span style="color: #808080;">=</span> @Generation <span style="color: #808080;">-</span> <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>
				<span style="color: #808080;">AND</span> aid <span style="color: #808080;">NOT</span> <span style="color: #808080;">IN</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> p <span style="color: #0000FF;">FROM</span> @Nodes<span style="color: #808080;">&#41;</span>
&nbsp;
		<span style="color: #0000FF;">END</span>
&nbsp;
	<span style="color: #008080;">-- Backtracing method: Traces the route back from target to start</span>
&nbsp;
	<span style="color: #0000FF;">DECLARE</span> @Backtrace <span style="color: #0000FF;">TABLE</span>
	<span style="color: #808080;">&#40;</span> p <span style="color: #0000FF;">INT</span> <span style="color: #808080;">&#41;</span>
&nbsp;
	<span style="color: #0000FF;">INSERT</span> @Backtrace <span style="color: #0000FF;">VALUES</span><span style="color: #808080;">&#40;</span>@<span style="color: #0000FF;">TO</span><span style="color: #808080;">&#41;</span>
&nbsp;
	<span style="color: #0000FF;">WHILE</span> @Generation <span style="color: #808080;">&gt;</span> <span style="color: #000;">0</span>
		<span style="color: #0000FF;">BEGIN</span>
			<span style="color: #0000FF;">DELETE</span> <span style="color: #0000FF;">FROM</span> @Nodes
			<span style="color: #0000FF;">WHERE</span> Generation <span style="color: #808080;">=</span> @Generation
				<span style="color: #808080;">AND</span> p <span style="color: #808080;">NOT</span> <span style="color: #808080;">IN</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SELECT</span> p <span style="color: #0000FF;">FROM</span> @Backtrace<span style="color: #808080;">&#41;</span>
&nbsp;
			<span style="color: #0000FF;">INSERT</span> @Backtrace
				<span style="color: #808080;">&#40;</span> p <span style="color: #808080;">&#41;</span>
&nbsp;
			<span style="color: #0000FF;">SELECT</span> <span style="color: #0000FF;">DISTINCT</span> r
			<span style="color: #0000FF;">FROM</span> @Nodes
			<span style="color: #0000FF;">WHERE</span> Generation <span style="color: #808080;">=</span> @Generation
&nbsp;
			<span style="color: #0000FF;">SELECT</span> @Generation <span style="color: #808080;">=</span> @Generation <span style="color: #808080;">-</span> <span style="color: #000;">1</span>
		<span style="color: #0000FF;">END</span>
<span style="color: #0000FF;">END</span>
&nbsp;
<span style="color: #0000FF;">SELECT</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">FROM</span> @Nodes <span style="color: #0000FF;">ORDER</span> <span style="color: #0000FF;">BY</span> Generation, r, p</pre></td></tr></table></div>

<p>The procedure returns the following columns:</p>
<ul>
<li><strong>Generation</strong>: The amount of generations of leaf node expansion</li>
<li><strong>P</strong>: The progressive node ID</li>
<li><strong>R</strong>: The regressive node ID</li>
</ul>
<p>The regressive ID is in fact the node&#8217;s parent and the progressive ID its child. This way we can obtain the (outward) direction in the result set. Results can represent multiple shortest routes as long as they both have the minimum amount of steps (Generations) necessary.</p>
<p>If we would want to obtain the shortest route(s) between two nodes with ID&#8217;s 776 and 777 this would be a valid result.</p>
<p><strong>Execution of the Stored Procedure:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">EXEC BFS @<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">776</span><span style="color: #66cc66;">,</span>  @<span style="color: #993333; font-weight: bold;">TO</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">777</span></pre></div></div>

<p><strong>The result set:</strong></p>
<table border="1" cellspacing="1" cellpadding="2">
<tbody>
<tr>
<th align="left">Generation</th>
<th align="left">p</th>
<th align="left">r</th>
</tr>
<tr>
<td>0</td>
<td>776</td>
<td></td>
</tr>
<tr>
<td>1</td>
<td>2881</td>
<td>776</td>
</tr>
<tr>
<td>1</td>
<td>3198</td>
<td>776</td>
</tr>
<tr>
<td>2</td>
<td>3362</td>
<td>2881</td>
</tr>
<tr>
<td>2</td>
<td>1582</td>
<td>3198</td>
</tr>
<tr>
<td>3</td>
<td>1579</td>
<td>1582</td>
</tr>
<tr>
<td>3</td>
<td>1262</td>
<td>3362</td>
</tr>
<tr>
<td>4</td>
<td>777</td>
<td>1262</td>
</tr>
<tr>
<td>4</td>
<td>777</td>
<td>1579</td>
</tr>
</tbody>
</table>
<p>As you can see this result set proposes two shortest routes between nodes 776 and 777.</p>
<p>In practice this technique has its limitations. It is not heuristic so brute force is required. With each generation that the leafs expand there is an exponential amount of nodes to be dealt with. Luckily there are ways to chop in two the exponential strain this procedure poses for the DB. One of these is the <a href="http://en.wikipedia.org/wiki/Bidirectional_search" target="_blank">bidirectional search</a> method. Alas, I will not disclose <span style="text-decoration: underline;">that</span> particular implementation.</p>
<p>Go code or something <img src='http://www.martienus.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.martienus.com/code/t-sql-breadth-first-shortest-route-search-stored-procedure.html/feed</wfw:commentRss>
		<slash:comments>8688</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.352 seconds -->

