<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Aaron Akin</title>
	<atom:link href="http://aaronakinsql.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://aaronakinsql.wordpress.com</link>
	<description>&#34;All things being SQL&#34;</description>
	<lastBuildDate>Sun, 04 Dec 2011 05:15:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='aaronakinsql.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/a40b85b3789293108c77317fa03022ac?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Aaron Akin</title>
		<link>http://aaronakinsql.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://aaronakinsql.wordpress.com/osd.xml" title="Aaron Akin" />
	<atom:link rel='hub' href='http://aaronakinsql.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Stripping the time from a DATETIME value</title>
		<link>http://aaronakinsql.wordpress.com/2009/03/19/stripping-the-time-from-a-datetime-value/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/03/19/stripping-the-time-from-a-datetime-value/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 02:39:25 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/?p=120</guid>
		<description><![CDATA[Many times there is a need to strip the time off of a DATETIME value so you are left with the date only. I&#8217;ve seen a few different ways to handle this. To clarify, when I say a DATETIME value with no time, I really mean midnight (00:00:00.000) on that date. Converting to VARCHAR One [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=120&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Many times there is a need to strip the time off of a DATETIME value so you are left with the date only.  I&#8217;ve seen a few different ways to handle this.  To clarify, when I say a DATETIME value with no time, I really mean midnight (00:00:00.000) on that date.</p>
<p><strong>Converting to VARCHAR</strong></p>
<p>One way to remove the time from a DATETIME value is to convert it to a VARCHAR data type.  This is handy when you need the date returned as a VARCHAR value and when you need the option to return the date in any number of different formats, with or without the century (i.e. 2009 vs 09).  The full list of the different formats that are available using CONVERT is located in <a href="http://msdn.microsoft.com/en-us/library/ms187928.aspx" target="_blank">Books Online</a>.  Here is an example of a few the different formats.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;">DECLARE @dt DATETIME
SET @dt = GETDATE()

SELECT CONVERT(VARCHAR,@dt,1) AS Date1
     , CONVERT(VARCHAR,@dt,101) AS Date101
     , CONVERT(VARCHAR,@dt,12) AS Date12
     , CONVERT(VARCHAR,@dt,112) AS Date112</pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;">Date1      Date101    Date12     Date112
---------- ---------- ---------- ----------
03/19/09   03/19/2009 090319     20090319</pre>
<p>One thing to consider when comparing a DATETIME value to another DATETIME value that has been converted to VARCHAR, you should always convert it back to DATETIME.  This is called an explicit conversion when you use CAST or CONVERT to change a value to a different data type.  The comparison will still work properly without the explicit conversion, but this will cause SQL Server to convert it at runtime, called an implicit conversion, putting unneccesary overhead on the server.</p>
<p><strong>Using DATEADD and DATEDIFF</strong></p>
<p>Another way to remove the time from a DATETIME value is to use a combination of the DATEADD and DATEDIFF functions.  This is a good way to not only strip the time off of a particular DATETIME value, but you can also use that value to get other dates without the time.  Here is an example of a few different dates that can be returned using the current date as a reference point.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;">DECLARE @dt DATETIME
SET @dt = GETDATE()

SELECT DATEADD(DAY,DATEDIFF(DAY,0,@dt),0) AS Today
     , DATEADD(DAY,DATEDIFF(DAY,0,@dt),-1) AS Yesterday
     , DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0) AS FirstOfThisMonth
     , DATEADD(MONTH,DATEDIFF(MONTH,-1,@dt),-1) AS LastOfThisMonth
     , DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),-1) AS LastOfPrevMonth
     , DATEADD(YEAR,DATEDIFF(YEAR,0,@dt),0) AS FirstOfYear</pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;">Today               Yesterday           FirstOfThisMonth    LastOfThisMonth     LastOfPrevMonth     FirstOfYear
------------------- ------------------- ------------------- ------------------- ------------------- -------------------
2009-03-19 00:00:00 2009-03-18 00:00:00 2009-02-28 00:00:00 2009-03-31 00:00:00 2009-02-28 00:00:00 2009-01-01 00:00:00</pre>
<p><strong>ODBC Date/Time Escape Clauses</strong></p>
<p>Another interesting method I found recently involves ODBC date and time escape clauses.  I don&#8217;t really know much about these, but I thought they were intriguing.  There are 3 extensions, one for date (d), time (t), and timestamp (ts).  The only one I thought might be useful was the time extension.  Here&#8217;s an example of using this to retrieve today&#8217;s date with no time value.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;">SELECT {t '00:00:00'} AS Today</pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;">Today
-------------------
2009-03-19 00:00:00</pre>
<p>I could see this being handy if you only ever wanted to get the current date at midnight, but I haven&#8217;t found a way to pass in a variable or column to this, so it is limited to the current date only.  Just for kicks, here&#8217;s how you would use the date and timestamp escape clauses.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;">SELECT {ts '2009-03-19 00:00:00'}
     , {d '2009-03-19'}</pre>
<p>Both of these will return today&#8217;s date at midnight as well.  I&#8217;d be interested to see if anyone knows any other uses for these.</p>
<p>Aaron<span style="text-decoration:underline;"><br />
</span></p>
<br />Posted in SQL, TSQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/120/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=120&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/03/19/stripping-the-time-from-a-datetime-value/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Finding the major version number of your SQL Server instance</title>
		<link>http://aaronakinsql.wordpress.com/2009/03/18/finding-the-major-version-number-of-your-sql-server-instance/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/03/18/finding-the-major-version-number-of-your-sql-server-instance/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 02:38:18 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/?p=117</guid>
		<description><![CDATA[Occasionally, I need to determine which version of SQL Server I am connected to within a script so that I can write the proper code for that version. I’m never really concerned with the build number or which service pack I have installed. Instead, all I want is the major version number (7, 8, 9, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=117&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Occasionally, I need to determine which version of SQL Server I am connected to within a script so that I can write the proper code for that version.  I’m never really concerned with the build number or which service pack I have installed.  Instead, all I want is the major version number (7, 8, 9, 10, etc).</p>
<p>One of the difficult things about something that seems like it should be so simple is that some of the ways to check the version number only exist on certain versions.  Other ways give you way more info than you really need.</p>
<p>Recently, I was digging through a system stored procedure, which is always the best place to find cool code, and I came across the undocumented system function @@MICROSOFTVERSION which is used internally by Microsoft.</p>
<p>It returns a seemingly random number, but you can use a bitwise AND operator to find the major version number.</p>
<pre style="font-family:courier new;"><span style="color:blue;">SELECT</span> @@MICROSOFTVERSION / 0x01000000</pre>
<p>This will return the following based on your version of SQL Server:</p>
<p>7  (SQL 7	)<br />
8  (SQL 2000)<br />
9  (SQL 2005)<br />
10 (SQL 2008)</p>
<p>This will work on any version of SQL Server as of now, but since it is undocumented, it’s always possible that it could be removed in the future.</p>
<p>Aaron</p>
<br />Posted in SQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/117/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=117&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/03/18/finding-the-major-version-number-of-your-sql-server-instance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Nested Common Table Expressions</title>
		<link>http://aaronakinsql.wordpress.com/2009/03/18/nested-common-table-expressions/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/03/18/nested-common-table-expressions/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 02:01:18 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[CTE]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/?p=111</guid>
		<description><![CDATA[If you&#8217;ve looked up a Common Table Expressions in Books Online, you might have noticed that Microsoft says that you cannot have nested CTEs (meaning, you can&#8217;t define a CTE in the definition of another CTE. Although this is technically true, you can still accomplish the same functionality in a different manner. Here is an [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=111&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve looked up a Common Table Expressions in Books Online, you might have noticed that Microsoft says that you cannot have nested CTEs (meaning, you can&#8217;t define a CTE in the definition of another CTE.  Although this is technically true, you can still accomplish the same functionality in a different manner.<br />
<span id="more-111"></span></p>
<p>Here is an example of a simple CTE using the AdventureWorks database that will return a list of orders.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;"><code>USE AdventureWorks

;WITH CTE_Orders (OrderID, OrderDate) AS
(
  SELECT PurchaseOrderID, OrderDate
    FROM Purchasing.PurchaseOrderHeader h
)

SELECT * FROM CTE_Orders</code></pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;"><code>OrderID     OrderDate
----------- ----------
1           2001-05-17
2           2001-05-17
3           2001-05-17
4           2001-05-17
5           2001-05-31
...</code></pre>
<p>What isn&#8217;t very clear is the use of multiple CTE definitions in one statement.  Here is an example of multiple CTEs used in one statement.  Each CTE in the statement has its own definition, and the final SELECT statement is able to query both CTEs.  This will return a list of dates that orders were made along with the number of products ordered and the total amount of those products for each date.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;"><code>;WITH CTE_OrdersDetail (OrderID, OrderDetailQty, OrderDetailAmt) AS
(
  SELECT PurchaseOrderID, OrderQty, LineTotal
    FROM Purchasing.PurchaseOrderDetail
),

CTE_Orders (OrderID, OrderDate) AS
(
  SELECT PurchaseOrderID, OrderDate
    FROM Purchasing.PurchaseOrderHeader h
)

SELECT o.OrderDate, SUM(od.OrderDetailQty) AS TotalOrderQty, SUM(od.OrderDetailAmt) AS TotalOrderAmt
  FROM CTE_Orders o
    INNER JOIN CTE_OrdersDetail od ON o.OrderID = od.OrderID
  GROUP BY o.OrderDate
  ORDER BY o.OrderDate</code></pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;"><code>OrderDate  TotalOrderQty TotalOrderAmt
---------- ------------- -------------
2001-05-17 563           9491.518
2001-05-31 2765          94404.303
2002-01-14 718           39874.7685
2002-01-15 11931         259365.2145
2002-02-08 2768          50781.36
...</code></pre>
<p>If you take this concept of having multiple CTE definitions in one statement, you can then apply it to a statement with nested CTEs.  I&#8217;m using the following statement to return the same result set as in the previous example, but this time I want to know the number of orders for each date that had more than 100 products ordered.</p>
<pre style="background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border:#99b1ff 1px dotted;"><code>;WITH CTE_OrdersDetail (OrderID, OrderDetailQty, OrderDetailAmt) AS
(
  SELECT PurchaseOrderID, OrderQty, LineTotal
    FROM Purchasing.PurchaseOrderDetail
),

CTE_Orders (OrderID, OrderDate, IsLargeOrder) AS
(
  SELECT PurchaseOrderID, OrderDate
       , (
         SELECT CASE
                  WHEN SUM(OrderDetailQty) &gt;= 100 THEN 1
                  ELSE 0
                END
           FROM CTE_OrdersDetail d
           WHERE h.PurchaseOrderID = d.OrderID
         )
    FROM Purchasing.PurchaseOrderHeader h
)

SELECT o.OrderDate, SUM(od.OrderDetailQty) AS TotalOrderQty, SUM(od.OrderDetailAmt) AS TotalOrderAmt, SUM(o.IsLargeOrder) AS NumLargeOrders
  FROM CTE_Orders o
    INNER JOIN CTE_OrdersDetail od ON o.OrderID = od.OrderID
  GROUP BY o.OrderDate
  ORDER BY o.OrderDate</code></pre>
<pre style="background-color:#f1f7fb;width:100%;font-family:courier new;border:#99b1ff 1px dotted;"><code>OrderDate  TotalOrderQty TotalOrderAmt         NumLargeOrders
---------- ------------- --------------------- --------------
2001-05-17 563           9491.518              1
2001-05-31 2765          94404.303             5
2002-01-14 718           39874.7685            1
2002-01-15 11931         259365.2145           26
2002-02-08 2768          50781.36              5
...</code></pre>
<p>As you can see from this example, the CTE_OrdersDetail expression is being referenced within the definition of the CTE_Orders expression, giving you the functionality of nested CTEs.  In order for a statement like this to work properly, you must declare each CTE definition before it is used in another CTE.  This means that since CTE_OrdersDetail is being reference within CTE_Orders, I must declare CTE_OrdersDetail first.  Otherwise, if the two definitions were switched, SQL would not be able to find the CTE_OrdersDetail object when it goes to verify the CTE_Orders expression.</p>
<br />Posted in CTE, SQL, SQL 2005, SQL 2008, TSQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/111/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=111&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/03/18/nested-common-table-expressions/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Deleting Duplicate Records</title>
		<link>http://aaronakinsql.wordpress.com/2009/02/19/deleting-duplicate-records/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/02/19/deleting-duplicate-records/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 00:42:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/02/19/deleting-duplicate-records/</guid>
		<description><![CDATA[I was helping someone out today on Experts-Exchange who had a quite a few duplicate records in a table that he wanted to get rid of.&#160; Here&#8217;s an example of the data. SELECT * FROM People GO LastName FirstName -------- --------- Smith&#160;&#160;&#160; John Smith&#160;&#160;&#160; John Smith&#160;&#160;&#160; John Jackson&#160; Tom Jones&#160;&#160;&#160; Sarah Jones&#160;&#160;&#160; Sarah Williams Jessica [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=108&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I was helping someone out today on <a target="_blank" href="http://www.experts-exchange.com/">Experts-Exchange</a> who had a quite a few duplicate records in a table that he wanted to get rid of.&#160; Here&#8217;s an example of the data.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">SELECT * FROM People
GO</pre>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">LastName FirstName
-------- ---------
Smith&#160;&#160;&#160; John
Smith&#160;&#160;&#160; John
Smith&#160;&#160;&#160; John
Jackson&#160; Tom
Jones&#160;&#160;&#160; Sarah
Jones&#160;&#160;&#160; Sarah
Williams Jessica</pre>
<p>As you can see, there is nothing in this table that makes each row unique, and therefore you cannot delete one of the records for John Smith without deleting both records.</p>
<p><span id="more-108"></span></p>
<p>The easiest way to delete these duplicates is to add a new IDENTITY column to the table.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">ALTER TABLE People ADD ID INT IDENTITY(1,1)
GO

SELECT * FROM People
GO</pre>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastName FirstName
----------- -------- ---------
1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Smith&#160;&#160;&#160; John
2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Smith&#160;&#160;&#160; John
3&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Smith&#160;&#160;&#160; John
4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Jackson&#160; Tom
5&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Jones&#160;&#160;&#160; Sarah
6&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Jones&#160;&#160;&#160; Sarah
7&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Williams Jessica</pre>
<p>This will provide us with a unique value across all records, which we can use to find and delete the duplicate rows.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">DELETE FROM People WHERE ID NOT IN
&#160; (
&#160; --Return only the ID for records we want to keep
&#160; SELECT ID
&#160;&#160;&#160; FROM
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; --Return one ID for each person
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT MIN(ID) AS ID, LastName, FirstName
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM People
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GROUP BY LastName, FirstName
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) a
&#160; )
GO

SELECT * FROM People
GO</pre>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LastName FirstName
----------- -------- ---------
1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Smith&#160;&#160;&#160; John
4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Jackson&#160; Tom
5&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Jones&#160;&#160;&#160; Sarah
7&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Williams Jessica</pre>
<p>We are now left with only one record for each person.&#160; You can now drop the ID column from the table.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">ALTER TABLE People DROP COLUMN ID
GO</pre>
<p>-A</p>
<br />Posted in TSQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/108/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=108&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/02/19/deleting-duplicate-records/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>SSIS 2005 Connections from SSMS 2008</title>
		<link>http://aaronakinsql.wordpress.com/2009/02/18/ssis-2005-connections-from-ssms-2008/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/02/18/ssis-2005-connections-from-ssms-2008/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 23:17:36 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[SSIS]]></category>
		<category><![CDATA[SSMS]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/?p=101</guid>
		<description><![CDATA[After I first installed SQL 2008, I tried to connect to SSIS 2005, and to my surprise, received the error, &#8220;Connect to SSIS Service on machine xxx failed: Class not registered.&#8221;  Thanks for the descriptive error message, Microsoft. Apparently, you cannot connect to SSIS 2005 from within SSMS 2008.  I found a feedback ticket with Microsoft that confirms [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=101&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>After I first installed SQL 2008, I tried to connect to SSIS 2005, and to my  surprise, received the error, &#8220;<strong>Connect to SSIS Service on machine xxx failed:  Class not registered.</strong>&#8221;  Thanks for the descriptive error message, Microsoft.</p>
<p><img class="alignnone size-full wp-image-102" title="Cannot Connect to Server" src="http://aaronakinsql.files.wordpress.com/2009/02/cannotconnect.jpg" alt="Cannot Connect to Server" width="611" height="250" /></p>
<p>Apparently, you cannot connect to SSIS 2005 from within SSMS 2008.  I found a  <a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=315076" target="_blank">feedback  ticket</a> with Microsoft that confirms the issue, though I wasn&#8217;t completely clear if  they are planning on fixing it or not.</p>
<p>So, for those of you who installed SSMS 2008, make sure you keep SSMS 2005  installed as well if you still have SSIS 2005 packages out there…even if it is a  pain to have to switch back and forth.</p>
<p>-A</p>
<br />Posted in SQL 2005, SQL 2008, SSIS, SSMS  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/101/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=101&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/02/18/ssis-2005-connections-from-ssms-2008/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>

		<media:content url="http://aaronakinsql.files.wordpress.com/2009/02/cannotconnect.jpg" medium="image">
			<media:title type="html">Cannot Connect to Server</media:title>
		</media:content>
	</item>
		<item>
		<title>Sorting SSIS Packages &amp; Folders in SSMS</title>
		<link>http://aaronakinsql.wordpress.com/2009/02/02/sorting-ssis-packages-folders-in-ssms/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/02/02/sorting-ssis-packages-folders-in-ssms/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 23:24:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[SSMS]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/02/02/sorting-ssis-packages-folders-in-ssms/</guid>
		<description><![CDATA[It had always bothered me when I opened a SQL 2005 Integrated Services instance to find an SSIS package, only to see that the folders and packages were not in alphabetical order. It wasn&#8217;t long before this started to get irritate me.&#160; I did some digging and found 2 system stored procedures (sp_dts_listfolders and sp_dts_listpackages) [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=91&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It had always bothered me when I opened a SQL 2005 Integrated Services instance to find an SSIS package, only to see that the folders and packages were not in alphabetical order.</p>
<p><img alt="SSMS Object Explorer" src="http://aaronakinsql.files.wordpress.com/2009/02/ssms-object-explorer-not-sorted.jpg" /></p>
<p>It wasn&#8217;t long before this started to get irritate me.&#160; I did some digging and found 2 system stored procedures (<strong>sp_dts_listfolders</strong> and <strong>sp_dts_listpackages</strong>) in the msdb database that SQL Server uses to display the packages and folders in menus.</p>
<p> <span id="more-91"></span>
<p>The first procedure, <strong>msdb.dbo.sp_dts_listfolders</strong>, returns the list of folders.&#160; You can modify the procedure and add an ORDER BY clause to the end of the query, as shown below.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">USE [msdb]
GO

ALTER PROCEDURE [dbo].[sp_dts_listfolders]
&#160; @parentfolderid uniqueidentifier = NULL
AS
&#160; SELECT
&#160;&#160; folderid,
&#160;&#160; parentfolderid,
&#160;&#160; foldername
&#160; FROM
&#160;&#160;&#160;&#160;&#160; sysdtspackagefolders90
&#160; WHERE
&#160;&#160;&#160;&#160;&#160; [parentfolderid] = @parentfolderid OR
&#160;&#160;&#160;&#160;&#160; (@parentfolderid IS NULL AND [parentfolderid] IS NULL)
&#160; <font color="red"><strong>ORDER BY foldername</strong></font></pre>
<p>The second procedure, <strong>msdb.dbo.sp_dts_listpackages</strong>, returns the list of packages.&#160; You can modify this procedure in the same way by adding the ORDER BY clause, as shown below.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">USE [msdb]
GO

ALTER PROCEDURE [dbo].[sp_dts_listpackages]
&#160; @folderid uniqueidentifier
AS
&#160; SELECT
&#160;&#160;&#160;&#160;&#160; name,
&#160;&#160;&#160;&#160;&#160; id,
&#160;&#160;&#160;&#160;&#160; description,
&#160;&#160;&#160;&#160;&#160; createdate,
&#160;&#160;&#160;&#160;&#160; folderid,
&#160;&#160;&#160;&#160;&#160; datalength(packagedata),
&#160;&#160;&#160;&#160;&#160; vermajor,
&#160;&#160;&#160;&#160;&#160; verminor,
&#160;&#160;&#160;&#160;&#160; verbuild,
&#160;&#160;&#160;&#160;&#160; vercomments,
&#160;&#160;&#160;&#160;&#160; verid
&#160; FROM
&#160;&#160;&#160;&#160;&#160; sysdtspackages90
&#160; WHERE
&#160;&#160;&#160;&#160;&#160; [folderid] = @folderid
&#160; <font color="red"><strong>ORDER BY name</strong></font></pre>
<p>Now if you refresh your menu, you&#8217;ll see that everything is now ordered.</p>
<p><img alt="SSMS Object Explorer" src="http://aaronakinsql.files.wordpress.com/2009/02/ssms-object-explorer-sorted.jpg" /></p>
<p>In SQL 2008, these procedures are now called <strong>msdb.dbo.sp_ssis_listfolders</strong> and <strong>msdb.dbo.sp_ssis_listpackages</strong>, and Microsoft has already added the ORDER BY clauses to both queries.</p>
<br />Posted in SQL, SQL 2005, SQL 2008, SSMS  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=91&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/02/02/sorting-ssis-packages-folders-in-ssms/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>

		<media:content url="http://aaronakinsql.files.wordpress.com/2009/02/ssms-object-explorer-not-sorted.jpg" medium="image">
			<media:title type="html">SSMS Object Explorer</media:title>
		</media:content>

		<media:content url="http://aaronakinsql.files.wordpress.com/2009/02/ssms-object-explorer-sorted.jpg" medium="image">
			<media:title type="html">SSMS Object Explorer</media:title>
		</media:content>
	</item>
		<item>
		<title>Recursive Common Table Expressions &#8211; Part 2</title>
		<link>http://aaronakinsql.wordpress.com/2009/01/21/recursive-common-table-expressions-part-2/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/01/21/recursive-common-table-expressions-part-2/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 01:48:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[CTE]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/01/05/recursive-common-table-expressions-part-2/</guid>
		<description><![CDATA[In my last post, Recursive Common Table Expressions – Part 1, I gave a brief overview of common table expressions (CTE) and gave some examples on how to use them to write recursive queries.&#160; The first two examples showed how to find the missing numbers, or dates, in a sequence.&#160; It was assumed that you [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=78&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In my last post, <a href="http://aaronakinsql.wordpress.com/2009/01/20/recursive-common-table-expressions-part-1/">Recursive Common Table Expressions – Part 1</a>, I gave a brief overview of common table expressions (CTE) and gave some examples on how to use them to write recursive queries.&#160; The first two examples showed how to find the missing numbers, or dates, in a sequence.&#160; It was assumed that you already had a table with a list of numbers or dates in it.&#160; The examples in this post will expand on the first two examples to show you how to build a range of numbers or dates given a starting and ending point.</p>
<p> <span id="more-78"></span>
<p><strong>Example 3 – Create a sequential range of numbers</strong></p>
<p>In this example, I’ll show you how to use a CTE to create a range of sequential numbers given a minimum (lower limit) and maximum (upper limit) number.&#160; First, I’m going to declare the variables that I&#8217;ll be using.&#160; The <strong>@LowerLimit</strong> and <strong>@UpperLimit</strong> variables will be used as starting and ending points of the range of numbers.&#160; The <strong>@IncludeLowerLimit</strong> and <strong>@IncludeUpperLimit</strong> variables will tell the query if it needs to return the <strong>@LowerLimit</strong> and <strong>@UpperLimit</strong> values in the result set.&#160; In this case, I want to use the range from 15 to 20, and I do want the limits to be a part of the result set.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">DECLARE
&#160;&#160;&#160;&#160;&#160; @LowerLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INT&#160;&#160;&#160; -- Lower limit
&#160;&#160;&#160; , @UpperLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INT&#160;&#160;&#160; -- Upper limit
&#160;&#160;&#160; , @IncludeLowerLimit&#160;&#160;&#160; BIT&#160;&#160;&#160; -- Includes lower limit in results
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; BIT&#160;&#160;&#160; -- Includes upper limit in results

SELECT
&#160;&#160;&#160;&#160;&#160; @LowerLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = 15
&#160;&#160;&#160; , @UpperLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = 20
&#160;&#160;&#160; , @IncludeLowerLimit&#160;&#160;&#160; = 1
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; = 1

;WITH CTE_Range (Number) AS
(
&#160; SELECT @LowerLimit + 1
&#160; UNION ALL
&#160; SELECT Number + 1
&#160;&#160;&#160; FROM CTE_Range
&#160;&#160;&#160; WHERE Number &lt; @UpperLimit + 1
)
SELECT Number - @IncludeLowerLimit AS Number
&#160; FROM CTE_Range
&#160; WHERE Number &lt; (@UpperLimit + @IncludeLowerLimit + @IncludeUpperLimit)
&#160; ORDER BY Number</pre>
<p>This query will return a sequential range of numbers from 15 through 20.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">Number
-----------
15
16
17
18
19
20

(6 row(s) affected)</pre>
<p>You can also change the <strong>@IncludeLowerLimit</strong> and <strong>@IncludeUpperLimit</strong> variables to shift the ranges a little.&#160; I&#8217;ll now change the values for both of these variables to 0 and rerun the query.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">SELECT
&#160;&#160;&#160;&#160;&#160; @IncludeLowerLimit&#160;&#160;&#160; = 0
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; = 0</pre>
<p>This query will now only return a sequential range of numbers from 16 through 19.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">Number
-----------
16
17
18
19

(4 row(s) affected)</pre>
<p>&#160;</p>
<p><strong>Example 4 – Create a sequential range of dates</strong></p>
<p>This example takes the same concept from example 3 and applies it to datetime values instead of numbers.&#160; First, I’m going to declare the variables that I&#8217;ll be using.&#160; The <strong>@LowerLimit</strong> and <strong>@UpperLimit</strong> variables will be used as starting and ending points of the range of datetime values.&#160; The <strong>@IncludeLowerLimit</strong> and <strong>@IncludeUpperLimit</strong> variables will tell the query if it needs to return the <strong>@LowerLimit</strong> and <strong>@UpperLimit</strong> values in the result set.</p>
<p>The one variable that I added to this example is the <strong>@RangeInterval</strong> variable.&#160; This allows you to specify the number of years, months, days, hours, minutes, seconds, etc. between the two datetime limits that should be returned in the result set.&#160; If you want to change the datepart value (i.e. MONTH, DAY, HOUR, etc.), you will have to change that manually since the datepart value cannot be assigned from a variable.&#160; However, you could add some more custom code to get this to work from a variable.</p>
<p>In this case, I&#8217;m going to use the range from 1/15/2009 12:00 AM to 1/20/2009 12:00 AM, use 1 day as the interval, and I do want the limits to be a part of the result set.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">DECLARE
&#160;&#160;&#160;&#160;&#160; @LowerLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DATETIME&#160;&#160; -- Lower limit
&#160;&#160;&#160; , @UpperLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DATETIME&#160;&#160; -- Upper limit
&#160;&#160;&#160; , @RangeInterval&#160;&#160;&#160;&#160;&#160;&#160;&#160; INT&#160;&#160;&#160;&#160;&#160;&#160;&#160; -- Interval between dates/times
&#160;&#160;&#160; , @IncludeLowerLimit&#160;&#160;&#160; BIT&#160;&#160;&#160;&#160;&#160;&#160;&#160; -- Includes lower limit in results
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; BIT&#160;&#160;&#160;&#160;&#160;&#160;&#160; -- Includes upper limit in results 

SELECT
&#160;&#160;&#160;&#160;&#160; @LowerLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = '1/15/2009 12:00 AM'
&#160;&#160;&#160; , @UpperLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = '1/20/2009 12:00 AM'
&#160;&#160;&#160; , @RangeInterval&#160;&#160;&#160;&#160;&#160;&#160;&#160; = 1
&#160;&#160;&#160; , @IncludeLowerLimit&#160;&#160;&#160; = 1
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; = 1

;WITH CTE_Range (Date) AS
(
&#160; SELECT DATEADD(DAY,@RangeInterval,@LowerLimit)
&#160; UNION ALL
&#160; SELECT DATEADD(DAY,@RangeInterval,Date)
&#160;&#160;&#160; FROM CTE_Range
&#160;&#160;&#160; WHERE Date &lt; DATEADD(DAY,@RangeInterval,@UpperLimit)
)
SELECT DATEADD(DAY,-@RangeInterval*@IncludeLowerLimit,Date) AS Date
&#160; FROM CTE_Range
&#160; WHERE Date &lt; DATEADD(DAY,@RangeInterval*@IncludeLowerLimit,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DATEADD(DAY,@RangeInterval*@IncludeUpperLimit,@UpperLimit))
&#160; ORDER BY Date</pre>
<p>This query will return a sequential range of datetime values every 1 day from 1/15/2009 12:00 AM to 1/20/2009 12:00 AM.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">Date
-----------------------
2009-01-15 00:00:00.000
2009-01-16 00:00:00.000
2009-01-17 00:00:00.000
2009-01-18 00:00:00.000
2009-01-19 00:00:00.000
2009-01-20 00:00:00.000

(6 row(s) affected)</pre>
<p>Now I&#8217;ll change the <strong>@RangeInterval</strong>, <strong>@LowerLimit</strong> and <strong>@UpperLimit</strong> variables to show you some different output.&#160; I&#8217;ll also need to change the datepart in every DATEADD function from DAY to HOUR so that it will return a datetime value for every 6 hours between 1/15/2009 4:00 AM and 1/16/2009 4:00 AM.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">SELECT
&#160;&#160;&#160;&#160;&#160; @LowerLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = '1/15/2009 4:00 AM'
&#160;&#160;&#160; , @UpperLimit&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = '1/16/2009 4:00 AM'
&#160;&#160;&#160; , @RangeInterval&#160;&#160;&#160;&#160;&#160;&#160;&#160; = 4
&#160;&#160;&#160; , @IncludeLowerLimit&#160;&#160;&#160; = 1
&#160;&#160;&#160; , @IncludeUpperLimit&#160;&#160;&#160; = 1

;WITH CTE_Range (Date) AS
(
&#160; SELECT DATEADD(HOUR,@RangeInterval,@LowerLimit)
&#160; UNION ALL
&#160; SELECT DATEADD(HOUR,@RangeInterval,Date)
&#160;&#160;&#160; FROM CTE_Range
&#160;&#160;&#160; WHERE Date &lt; DATEADD(HOUR,@RangeInterval,@UpperLimit)
)
SELECT DATEADD(HOUR,-@RangeInterval*@IncludeLowerLimit,Date) AS Date
&#160; FROM CTE_Range
&#160; WHERE Date &lt; DATEADD(HOUR,@RangeInterval*@IncludeLowerLimit,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DATEADD(HOUR,@RangeInterval*@IncludeUpperLimit,@UpperLimit))
&#160; ORDER BY Date</pre>
<p>This query will now only return a sequential range of datetime values every 6 hours from 1/15/2009 4:00 AM to 1/20/2009 4:00 AM.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#f1f7fb;width:100%;font-family:courier new;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">Date

-----------------------
2009-01-15 04:00:00.000
2009-01-15 10:00:00.000
2009-01-15 16:00:00.000
2009-01-15 22:00:00.000
2009-01-16 04:00:00.000

(5 row(s) affected)</pre>
<p>&#160;</p>
<p><strong>Conclusion</strong></p>
<p>You might wonder why you would ever need these queries, and I would have thought the same thing…until recently.&#160; I hope this helps someone out there.</p>
<br />Posted in CTE, SQL, SQL 2005, TSQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/78/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=78&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/01/21/recursive-common-table-expressions-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Recursive Common Table Expressions &#8211; Part 1</title>
		<link>http://aaronakinsql.wordpress.com/2009/01/20/recursive-common-table-expressions-part-1/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/01/20/recursive-common-table-expressions-part-1/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 00:43:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[CTE]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/01/20/recursive-common-table-expressions-part-1/</guid>
		<description><![CDATA[Introduction I recently had a project that required me to find the number of employees who were scheduled for every 15 minute increment, for every business day for a week, and for many stores.&#160; Yikes!&#160; Sure, I could use tons of loops and temp tables to do this, but I&#8217;m all about set based queries [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=63&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Introduction</strong></p>
<p>I recently had a project that required me to find the number of employees who were scheduled for every 15 minute increment, for every business day for a week, and for many stores.&#160; Yikes!&#160; Sure, I could use tons of loops and temp tables to do this, but I&#8217;m all about set based queries whenever possible&#8230;and I knew this was possible and I love a challenge!</p>
<p>It finally occurred to me that I could use the self-referencing (recursive) capabilities of Common Table Expressions (introduced in SQL 2005) to the mimic loops I needed to accomplish my goal.</p>
<p>I took some of the recursive CTE queries that I came up with for my project and turned them into 4 examples.&#160; It was quite a bit of info, so I&#8217;ll be spreading them across 2 posts.</p>
<p> <span id="more-63"></span><strong>   <br />What is a Common Table Expression (CTE)?</strong>
</p>
<p>Books Online defines a CTE as a temporary result set that is defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement. A CTE is similar to a derived table in that it is not stored as an object and lasts only for the duration of the query. Unlike a derived table, a CTE can be self-referencing and can be referenced multiple times in the same query.</p>
<p>Here&#8217;s a very basic example of a CTE.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">USE AdventureWorks
GO

;WITH Employees (EmployeeID, JobTitle) AS
(
&#160;&#160;&#160; SELECT EmployeeID, Title
&#160;&#160;&#160;&#160;&#160; FROM HumanResources.Employee
)
SELECT *
&#160; FROM Employees</pre>
<p>As you can see in the example, I preceded the CTE with an semicolon.&#160; The reason for this is because if a CTE is not the first statement in a batch, the previous statement must always be terminated with a semicolon, and you will receive one of two errors.</p>
<p><span><font color="#ff0000" face="Courier New">Incorrect syntax near the keyword &#8216;with&#8217;. If this statement is a common table expression or an xmlnamespaces clause, the previous statement must be terminated with a semicolon.</font></span></p>
<p>or</p>
<p><span><font color="#ff0000" face="Courier New">Incorrect syntax near &#8216;Employees&#8217;.</font></span></p>
<p>In my example, the semicolon is not needed since GO starts a new batch and the CTE is the first statement in the batch, I always make a habit of starting them off with a semicolon in case I ever add a preceding statement.</p>
<p>
  <br /><strong>Recursive Queries</strong></p>
<p>One of the most powerful features of common table expressions is their ability to be self-referenced, allowing a recursive query.&#160; The most common use of a recursive query in a CTE is to create a hierarchy.&#160; For example, if you had an Employee table that had a column for the EmployeeID and another column for the ManagerEmployeeID, you could use a self-referencing CTE to build a hierarchical result set of an organizational chart.</p>
<p>Srinivas Sampath wrote a good <a target="_blank" href="http://www.sqlservercentral.com/articles/Development/recursivequeriesinsqlserver2005/1760/">article on building a hierarchy using a CTE</a> on <a target="_blank" href="http://www.sqlservercentral.com">sqlservercentral.com</a>, so I&#8217;m not going to go into much detail here.&#160; Instead, I figured I would show you other ways that a recursive query can be used within a CTE.</p>
<p>
  <br /><strong>Example 1 &#8211; Finding missing numbers in a sequence</strong></p>
<p>In this example, I&#8217;ll show you how to use a CTE to find missing numbers (gaps) in a range of sequential numbers.&#160; First, I&#8217;m going to create a temporary table and add some numbers to it.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">CREATE TABLE #Numbers (Num INT)

INSERT INTO #Numbers VALUES (1)
INSERT INTO #Numbers VALUES (3)
INSERT INTO #Numbers VALUES (6)
INSERT INTO #Numbers VALUES (10)</pre>
<p>Now, I can use a CTE to find the missing sequential numbers. </p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">;WITH CTE_MissingNumbers (MissingNum) AS
(
&#160;&#160;&#160;&#160; SELECT n1.Num + 1
&#160;&#160;&#160;&#160;&#160;&#160; FROM #Numbers n1
&#160;&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS (SELECT NULL FROM #Numbers n2 WHERE n2.Num = n1.Num + 1)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND n1.Num &lt; (SELECT MAX(Num) FROM #Numbers)
&#160;&#160;&#160;&#160; UNION ALL
&#160;&#160;&#160;&#160; SELECT cte.MissingNum + 1
&#160;&#160;&#160;&#160;&#160;&#160; FROM CTE_MissingNumbers cte
&#160;&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS (SELECT NULL FROM #Numbers n WHERE n.Num = cte.MissingNum + 1)
)
SELECT MissingNum
&#160; FROM CTE_MissingNumbers
&#160; ORDER BY MissingNum</pre>
<p>The first SELECT statement in the CTE will only return the first missing number in each gap, so in this case, it will return the numbers 2, 4, and 7.</p>
<p>The second SELECT statement in the CTE will return the remaining missing numbers, if any, in each gap, so in this case, it will return the numbers 5, 8, and 9.&#160; It does this by continually referencing itself and reevaluating the gaps.&#160; As the more numbers are returned, the gaps get smaller and smaller until all numbers are returned.&#160; Think of the CTE as a WHILE loop that runs the first statement in the CTE and missing numbers back into the table.&#160; The loop then would continue over and over until the SELECT statement no longer returned any results.</p>
<p>
  <br /><strong>Example 2 &#8211; Finding missing dates in a sequence</strong></p>
<p>This example takes the same concept from example 1 and applies it to dates instead of numbers.&#160; First, I&#8217;m going to create a temporary table and add some dates to it.</p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">CREATE TABLE #Dates (Date SMALLDATETIME) 

INSERT INTO #Dates VALUES ('1/1/2009')
INSERT INTO #Dates VALUES ('1/3/2009')
INSERT INTO #Dates VALUES ('1/6/2009')
INSERT INTO #Dates VALUES ('1/10/2009')</pre>
<p>Now, I can use a CTE to find the missing sequential dates. </p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">;WITH CTE_MissingDates (MissingDate) AS
(
&#160;&#160;&#160; SELECT DATEADD(DAY,1,d1.Date)
&#160;&#160;&#160;&#160;&#160; FROM #Dates d1
&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS (SELECT NULL FROM #Dates d2 WHERE d2.Date = DATEADD(DAY,1,d1.Date))
&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND d1.Date &lt; (SELECT MAX(Date) FROM #Dates)
&#160;&#160;&#160; UNION ALL
&#160;&#160;&#160; SELECT DATEADD(DAY,1,cte.MissingDate)
&#160;&#160;&#160;&#160;&#160; FROM CTE_MissingDates cte
&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS (SELECT NULL FROM #Dates d WHERE d.Date = DATEADD(DAY,1,cte.MissingDate))
)
SELECT MissingDate
&#160; FROM CTE_MissingDates
&#160; ORDER BY MissingDate</pre>
<p>The only thing I really had to change to return missing dates instead of numbers was adding the DATEADD function.&#160; This will find all of the missing days, but for this to work, all of the time values in the Date column must all be the same.&#160; If your date values are not the same, you can strip off the time values as shown in red below: </p>
<pre style="border-bottom:#99b1ff 1px dotted;border-left:#99b1ff 1px dotted;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;overflow:auto;border-top:#99b1ff 1px dotted;border-right:#99b1ff 1px dotted;">TRUNCATE TABLE #Dates

INSERT INTO #Dates VALUES ('1/1/2009 5:00 PM')
INSERT INTO #Dates VALUES ('1/3/2009 3:00 PM')
INSERT INTO #Dates VALUES ('1/6/2009 1:00 PM')
INSERT INTO #Dates VALUES ('1/10/2009 2:00 PM')

;WITH CTE_MissingDates (MissingDate) AS
(
&#160;&#160;&#160;&#160; SELECT DATEADD(DAY,1,<strong><span style="color:#ff0000;">DATEDIFF(DAY,0,d1.Date)</span></strong>)
&#160;&#160;&#160;&#160;&#160;&#160; FROM #Dates d1
&#160;&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT NULL
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM #Dates d2
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE <strong><span style="color:#ff0000;">DATEADD(DAY,0,DATEDIFF(DAY,0,d2.Date))</span></strong> = DATEADD(DAY,1,<strong><span style="color:#ff0000;">DATEDIFF(DAY,0,d1.Date)</span>)</strong>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND d1.Date &lt; (SELECT MAX(Date) FROM #Dates)
&#160;&#160;&#160;&#160; UNION ALL&#160;&#160;&#160;&#160; SELECT DATEADD(DAY,1,cte.MissingDate)
&#160;&#160;&#160;&#160;&#160;&#160; FROM CTE_MissingDates cte
&#160;&#160;&#160;&#160;&#160;&#160; WHERE NOT EXISTS
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT NULL
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM #Dates d
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE DATEADD(DAY,0,<span style="color:#ff0000;"><strong>DATEDIFF(DAY,0,d.Date)</strong></span>) = DATEADD(DAY,1,cte.MissingDate)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )
)
SELECT MissingDate
&#160; FROM CTE_MissingDates
&#160; ORDER BY MissingDate</pre>
<p><strong><br />
    <br />Conclusion</strong></p>
<p>Here are two examples of using common table expressions to find missing numbers and dates in a sequence.&#160; In my <a href="http://aaronakinsql.wordpress.com/2009/01/21/recursive-common-table-expressions-part-2/">next post</a>, I&#8217;ll show you a few more examples of recursive queries with common table expressions based off of the examples in this post.</p>
<br />Posted in CTE, SQL, SQL 2005, TSQL  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/63/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=63&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/01/20/recursive-common-table-expressions-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Failed to lock variable for read access in SSIS</title>
		<link>http://aaronakinsql.wordpress.com/2009/01/14/failed-to-lock-variable-for-read-access-in-ssis/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/01/14/failed-to-lock-variable-for-read-access-in-ssis/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 23:37:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[Checkpoints]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/01/20/failed-to-lock-variable-for-read-access-in-ssis/</guid>
		<description><![CDATA[I was working on a new SSIS package recently, and in the process of trying to fix an issue with my package, I created an entirely new problem.&#160; My package now starting failing with the following error: Error: Failed to lock variable XXXX for read access with error 0xC0010001 &#34;The variable cannot be found. This [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=60&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I was working on a new SSIS package recently, and in the process of trying to fix an issue with my package, I created an entirely new problem.&#160; My package now starting failing with the following error:</p>
<blockquote><p><strong><font size="2" face="Arial">Error: Failed to lock variable XXXX for read access with error 0xC0010001 &quot;The variable cannot be found. This occurs when an attempt is made to retrieve a variable from the Variables collection on a container during execution of the package, and the variable is not there. The variable name may have changed or the variable is not being created.&quot;</font></strong></p>
</blockquote>
<p>It was so frustrating that I figured I would post it here in case anyone else comes across the same problem.</p>
<p>If you&#8217;ve ever seen this error before, you&#8217;ll most likely find that it is caused by a script task/component that is referencing a variable that no longer exists.&#160; In my case, I had no scripts but I did change some of my package variables.</p>
<p>After a while of trying to figure out what would cause this issue, I finally realized that my package had checkpoints enabled.&#160; When checkpoints are enable, details about the variables are written to the checkpoint file when the package is executed.</p>
<p>In the process of fixing the original problem with my package, I deleted some of the existing variables.&#160; I made sure to update all of my tasks that referenced the deleted variables, but I forgot to delete the checkpoint file before restarting the package.</p>
<p>When the checkpoint file was read upon execution, it tried to assign a value to the variables that were deleted, but since they did not exist anymore, I got this error.</p>
<p>I guess the point is, if you make changes to the structure of a package when checkpoints are enabled and a checkpoint file exists, it might be worth your time to delete the file before restarting the package with the new changes in effect.</p>
<p>-A</p>
<br />Posted in Checkpoints, SSIS  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/60/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=60&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/01/14/failed-to-lock-variable-for-read-access-in-ssis/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
		<item>
		<title>Cleaning Recent Projects List in Visual Studios</title>
		<link>http://aaronakinsql.wordpress.com/2009/01/05/cleaning-recent-projects-list-in-visual-studios/</link>
		<comments>http://aaronakinsql.wordpress.com/2009/01/05/cleaning-recent-projects-list-in-visual-studios/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 00:16:00 +0000</pubDate>
		<dc:creator>Aaron Akin</dc:creator>
				<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[Visual Studios (BIDS)]]></category>

		<guid isPermaLink="false">http://aaronakinsql.wordpress.com/2009/01/05/cleaning-recent-projects-list-in-vs/</guid>
		<description><![CDATA[I’m always creating a bunch of projects in Visual Studios for testing purposes, all of which clutter up my Recent Projects list on the VS Start Page.&#160; If you’re like me and want to clean up this list, make sure Visual Studios is closed and then open up the Registry Editor (Start &#62; Run &#62; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=52&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I’m always creating a bunch of projects in Visual Studios for testing purposes, all of which clutter up my Recent Projects list on the VS Start Page.&#160; If you’re like me and want to clean up this list, make sure Visual Studios is closed and then open up the Registry Editor (Start &gt; Run &gt; regedit) and find the following key:</p>
<p><strong>Visual Studios 8.0 (SQL 2005):      <br /></strong>HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\ProjectMRUList</p>
<p><strong>Visual Studios 9.0 (SQL 2008):      <br /></strong>HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\ProjectMRUList</p>
<p>Here you’ll find a list of keys that represent the projects/solutions that appear in your Recent Projects.&#160; You can either delete all of these entries, or just specific ones.&#160; Be careful if you only delete specific ones though.&#160; If you have 4 items (File1, File2, File3, File4) and you delete File2, only File1 will appear in your Recent Projects list.&#160; To fix this, you’ll just need to rename the rest of the keys so that there are no gaps in the sequential numbering.&#160; In this case, you would need to rename File3 to File2 and File4 to File3.</p>
<p>When you re-open Visual Studios, you should find a much cleaner list.</p>
<p>-A</p>
<br />Posted in SQL 2005, SQL 2008, Visual Studios (BIDS)  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/aaronakinsql.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/aaronakinsql.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/aaronakinsql.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=aaronakinsql.wordpress.com&amp;blog=6092380&amp;post=52&amp;subd=aaronakinsql&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://aaronakinsql.wordpress.com/2009/01/05/cleaning-recent-projects-list-in-visual-studios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f2060a6b383b012d26c47b6d818427f?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=PG" medium="image">
			<media:title type="html">Aaron</media:title>
		</media:content>
	</item>
	</channel>
</rss>
