<?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>Greylurk &#187; T-SQL</title>
	<atom:link href="http://greylurk.com/index.php/category/t-sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://greylurk.com</link>
	<description>Ramblings of a distracted techie</description>
	<lastBuildDate>Tue, 06 Sep 2011 17:22:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Comma Separated results, without a Cursor</title>
		<link>http://greylurk.com/index.php/2010/03/comma-separated-results-without-a-cursor/</link>
		<comments>http://greylurk.com/index.php/2010/03/comma-separated-results-without-a-cursor/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 02:00:54 +0000</pubDate>
		<dc:creator>Adam N.</dc:creator>
				<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://greylurk.com/?p=101</guid>
		<description><![CDATA[I&#8217;ve been writing T-SQL for years, and I&#8217;ve often found a case where I want to collapse a rowset containing a single column into a comma separated list. I&#8217;ve taken a few swags at it over the years, usually involving using a cursor and an accumulator string. Mostly though, I&#8217;ve just passed the whole rowset [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been writing T-SQL for years, and I&#8217;ve often found a case where I want to collapse a rowset containing a single column into a comma separated list.  I&#8217;ve taken a few swags at it over the years, usually involving using a cursor and an accumulator string.  Mostly though, I&#8217;ve just passed the whole rowset up the toolchain to my middleware, and dealt with it at the ColdFusion level.  However, today I found a case where that just wasn&#8217;t an option, so I started digging a bit more, and found a great solution at <a href="http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string">SQLTeam.com</a>.  Here&#8217;s the basics of their approach:</p>
<p>Say you have user, and a pile of associated permissions, like so:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> <span style="color: #0000FF;">User</span> <span style="color: #808080;">&#40;</span> 
  userId <span style="color: #0000FF;">int</span> autoincrement not null <span style="color: #0000FF;">primary</span> <span style="color: #0000FF;">key</span>
  username <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">100</span><span style="color: #808080;">&#41;</span>, 
  ... 
<span style="color: #808080;">&#41;</span> 
&nbsp;
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> UserPermission<span style="color: #808080;">&#40;</span> 
  userID <span style="color: #0000FF;">int</span> not null,
  permissionID <span style="color: #0000FF;">int</span> not null
<span style="color: #808080;">&#41;</span></pre></div></div>

<p>Now say you want to get a comma separated list of permissions for a given user.  You might think of using a cursor, or some other obscure method, but there&#8217;s an easy way:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">DECLARE</span> @UserPermissionList <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">MAX</span><span style="color: #808080;">&#41;</span>
&nbsp;
<span style="color: #0000FF;">SELECT</span> @UserPermissions <span style="color: #808080;">=</span> <span style="color: #0000FF;">COALESCE</span><span style="color: #808080;">&#40;</span> @UserPermissions <span style="color: #808080;">+</span><span style="color: #FF0000;">','</span>, <span style="color: #FF0000;">''</span> <span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span> PermissionID <span style="color: #0000FF;">as</span> <span style="color: #0000FF;">Varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">12</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">&#41;</span>
<span style="color: #0000FF;">FROM</span> UserPermission
<span style="color: #0000FF;">WHERE</span> UserID <span style="color: #808080;">=</span> @UserID
&nbsp;
<span style="color: #0000FF;">SELECT</span> <span style="color: #0000FF;">User</span>.<span style="color: #808080;">*</span>, @userPermissionList <span style="color: #0000FF;">as</span> PermissionList
<span style="color: #0000FF;">FROM</span> <span style="color: #0000FF;">User</span> 
<span style="color: #0000FF;">WHERE</span> UserID <span style="color: #808080;">=</span> @userID</pre></div></div>

<p>Voila, you&#8217;ve got a comma separated list of permissions, without using a cursor.   For those of you in the NoSQL crowd, you&#8217;ll note that really the COALESCE here is functioning very similarly to a &#8220;reduce&#8221; function from a map/reduce algorithm.  This approach could therefore open up some other interesting avenues for design.</p>
<p>I still wish there was a &#8220;JOIN()&#8221; aggregate function, but until that happens, we&#8217;re not totally paralyzed.</p>
<p><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service google_plusone" src="https://plusone.google.com/u/0/_/%2B1/fastbutton?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;size=medium&amp;count=false" scrolling="no" style="border:none;overflow:hidden;width:32px;height:20px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service google_plusone" src="https://plusone.google.com/u/0/_/%2B1/fastbutton?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;size=medium&amp;count=false" scrolling="no" style="border:none;overflow:hidden;width:32px;height:20px"></iframe><!--<![endif]--><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service twitter_tweet" src="http://platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;counturl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;count=none&amp;text=Comma%20Separated%20results%2C%20without%20a%20Cursor" scrolling="no" style="border:none;overflow:hidden;width:55px;height:20px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service twitter_tweet" src="http://platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;counturl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;count=none&amp;text=Comma%20Separated%20results%2C%20without%20a%20Cursor" scrolling="no" style="border:none;overflow:hidden;width:55px;height:20px"></iframe><!--<![endif]--><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service facebook_like" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;layout=button_count&amp;show_faces=false&amp;width=75&amp;action=like&amp;colorscheme=light&amp;height=20&amp;ref=addtoany" scrolling="no" style="border:none;overflow:hidden;width:90px;height:21px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service facebook_like" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;layout=button_count&amp;show_faces=false&amp;width=75&amp;action=like&amp;colorscheme=light&amp;height=20&amp;ref=addtoany" scrolling="no" style="border:none;overflow:hidden;width:90px;height:21px"></iframe><!--<![endif]--><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;linkname=Comma%20Separated%20results%2C%20without%20a%20Cursor" title="Delicious" rel="nofollow" target="_blank"><img src="http://greylurk.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_email" href="http://www.addtoany.com/add_to/email?linkurl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;linkname=Comma%20Separated%20results%2C%20without%20a%20Cursor" title="Email" rel="nofollow" target="_blank"><img src="http://greylurk.com/wp-content/plugins/add-to-any/icons/email.png" width="16" height="16" alt="Email"/></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2010%2F03%2Fcomma-separated-results-without-a-cursor%2F&amp;title=Comma%20Separated%20results%2C%20without%20a%20Cursor" id="wpa2a_2"><img src="http://greylurk.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://greylurk.com/index.php/2010/03/comma-separated-results-without-a-cursor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joining on Subqueries with SQL Server 2000+</title>
		<link>http://greylurk.com/index.php/2006/11/joining-on-subqueries-with-sql-server-2000/</link>
		<comments>http://greylurk.com/index.php/2006/11/joining-on-subqueries-with-sql-server-2000/#comments</comments>
		<pubDate>Mon, 27 Nov 2006 21:55:14 +0000</pubDate>
		<dc:creator>Adam N.</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[subquery]]></category>

		<guid isPermaLink="false">http://www.greylurk.com/wordpress/?p=17</guid>
		<description><![CDATA[Quite often I find myself wanting to get &#8220;the latest&#8221; result from a relational table. Normally this requires a subquery, which is slow. If I want more than one column from the relational table, I have to make multiple subqueries against a single table, which slows things down even more. However, recently, I discovered a [...]]]></description>
			<content:encoded><![CDATA[<p>Quite often I find myself wanting to get &#8220;the latest&#8221; result from a relational table.  Normally this requires a subquery, which is slow.  If I want more than one column from the relational table, I have to make multiple subqueries against a single table, which slows things down even more.  However, recently, I discovered a new method: joining against a subquery.</p>
<p>Say I have a list of events, and each one has a status report against it.  In my old scheme, I would have done something like this:</p>
<div style="background-color: #ffc; font: 10pt monospace; white-space: pre; border: 1px solid #ccc; margin: 2px 5px;overflow: auto;">SELECT e.id, e.title, e.date,</p>
<p>( SELECT TOP 1 r.Author FROM reports WHERE r.eventID = e.ID ORDER BY Date desc ) as ReportAuthor</p>
<p>( SELECT TOP 1 r.Date FROM reports WHERE r.eventID = e.ID ORDER BY Date desc ) as ReportDate</p>
<p>( SELECT TOP 1 r.Status FROM reports WHERE r.eventID = e.ID ORDER BY Date desc ) as ReportStatus</p>
<p>FROM Events e</p></div>
<p>However, the new way that I&#8217;ve found of doing things is:</p>
<div style="background-color: #ffc; font: 10pt monospace; white-space: pre; border: 1px solid #ccc; margin: 2px 5px;overflow: auto;">SELECT e.id, e.title, e.date, r.author as ReportAuthor, r.date as ReportDate, r.Status as reportStatus</p>
<p>FROM Events e</p>
<p>LEFT JOIN (</p>
<p>SELECT eventID, ReportDate, Author, Status</p>
<p>FROM Reports r1</p>
<p>WHERE ReportDate = (</p>
<p>SELECT TOP 1 ReportDate</p>
<p>FROM Reports R2</p>
<p>WHERE r1.eventID = R2.eventID</p>
<p>ORDER BY reportDate desc</p>
<p>)</p>
<p>ORDER BY Date desc</p>
<p>) r ON r.eventID = e.ID</p>
<p>WHERE &#8230;.</p></div>
<p>The second form executes significantly faster in the tests that I&#8217;ve done,</p>
<p><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service google_plusone" src="https://plusone.google.com/u/0/_/%2B1/fastbutton?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;size=medium&amp;count=false" scrolling="no" style="border:none;overflow:hidden;width:32px;height:20px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service google_plusone" src="https://plusone.google.com/u/0/_/%2B1/fastbutton?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;size=medium&amp;count=false" scrolling="no" style="border:none;overflow:hidden;width:32px;height:20px"></iframe><!--<![endif]--><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service twitter_tweet" src="http://platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;counturl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;count=none&amp;text=Joining%20on%20Subqueries%20with%20SQL%20Server%202000%2B" scrolling="no" style="border:none;overflow:hidden;width:55px;height:20px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service twitter_tweet" src="http://platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;counturl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;count=none&amp;text=Joining%20on%20Subqueries%20with%20SQL%20Server%202000%2B" scrolling="no" style="border:none;overflow:hidden;width:55px;height:20px"></iframe><!--<![endif]--><!--[if IE]><iframe frameborder="0" allowTransparency="true" class="addtoany_special_service facebook_like" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;layout=button_count&amp;show_faces=false&amp;width=75&amp;action=like&amp;colorscheme=light&amp;height=20&amp;ref=addtoany" scrolling="no" style="border:none;overflow:hidden;width:90px;height:21px"></iframe><![endif]--><!--[if !IE]><!--><iframe class="addtoany_special_service facebook_like" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;layout=button_count&amp;show_faces=false&amp;width=75&amp;action=like&amp;colorscheme=light&amp;height=20&amp;ref=addtoany" scrolling="no" style="border:none;overflow:hidden;width:90px;height:21px"></iframe><!--<![endif]--><a class="a2a_button_delicious" href="http://www.addtoany.com/add_to/delicious?linkurl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;linkname=Joining%20on%20Subqueries%20with%20SQL%20Server%202000%2B" title="Delicious" rel="nofollow" target="_blank"><img src="http://greylurk.com/wp-content/plugins/add-to-any/icons/delicious.png" width="16" height="16" alt="Delicious"/></a><a class="a2a_button_email" href="http://www.addtoany.com/add_to/email?linkurl=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;linkname=Joining%20on%20Subqueries%20with%20SQL%20Server%202000%2B" title="Email" rel="nofollow" target="_blank"><img src="http://greylurk.com/wp-content/plugins/add-to-any/icons/email.png" width="16" height="16" alt="Email"/></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fgreylurk.com%2Findex.php%2F2006%2F11%2Fjoining-on-subqueries-with-sql-server-2000%2F&amp;title=Joining%20on%20Subqueries%20with%20SQL%20Server%202000%2B" id="wpa2a_4"><img src="http://greylurk.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://greylurk.com/index.php/2006/11/joining-on-subqueries-with-sql-server-2000/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

