<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlservernation.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Development : SQL 2005</title><link>http://sqlservernation.com/blogs/development/archive/tags/SQL+2005/default.aspx</link><description>Tags: SQL 2005</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Pivot Rolling Periods : Dynamic, But Not!</title><link>http://sqlservernation.com/blogs/development/archive/2009/09/17/pivot-rolling-periods-dynamic-but-not.aspx</link><pubDate>Fri, 18 Sep 2009 03:53:00 GMT</pubDate><guid isPermaLink="false">a3dbd76b-19b9-441f-b40a-d79e8f433d35:283</guid><dc:creator>Kevin Cross</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlservernation.com/blogs/development/rsscomments.aspx?PostID=283</wfw:commentRss><comments>http://sqlservernation.com/blogs/development/archive/2009/09/17/pivot-rolling-periods-dynamic-but-not.aspx#comments</comments><description>&lt;p&gt;In the Article,&amp;nbsp;Pivot Rolling Periods Without Using Dynamic T-SQL (&lt;a target="_blank" title="Pivot Rolling Periods Without Using Dynamic T-SQL" href="http://experts-exchange.com/viewArticle.jsp?aid=654"&gt;experts-exchange.com/viewArticle.jsp?aid=654&lt;/a&gt;),&amp;nbsp;I explored the pivot of moving date based reports without the use of dynamic T-SQL, but still allow for re-use month after month without re-writing of code.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here is another introductory tidbit to SQL Server 2005&amp;#39;s PIVOT (&lt;a href="http://technet.microsoft.com/en-us/library/ms177410.aspx"&gt;technet.microsoft.com/en-us/library/ms177410.aspx&lt;/a&gt;). &amp;nbsp;We will&amp;nbsp;embrace the limitations of the PIVOT keyword requiring hard coded values / column names, but still provide nice reports that can be used in views or quick queries without getting into multi-line dynamic code. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;To play along, you can download and run the following DDL and data insert SQL script:&lt;/p&gt;
&lt;p&gt;(Please visit the site to view this media)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Okay, now we can play. &amp;nbsp;The following starts out by getting data greater or equal to last January 1st at midnight &amp;quot;dateadd(year, datediff(year, 0, getdate())-1, 0)&amp;quot;. &amp;nbsp;Then we employ a date function to make our datetime value non-specific to year (i.e., month(bk_date) will yield 1-12). &amp;nbsp;For this report, we want to have a year over year analysis of data by month so we also use year(bk_date) to get our grouped column heading which doesn&amp;#39;t affect us in the PIVOT since it will remain as data.&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;;with bks( byear, bmonth, amount )
as
(
select year(bk_date), month(bk_date), bk_amount
from bookings
where bk_date &amp;gt;= dateadd(year, datediff(year, 0, getdate())-1, 0)
)
select byear as &amp;quot;Sales Year&amp;quot;,
coalesce(&amp;quot;1&amp;quot;, 0.00) as January,
coalesce(&amp;quot;2&amp;quot;, 0.00) as February,
coalesce(&amp;quot;3&amp;quot;, 0.00) as March,
coalesce(&amp;quot;4&amp;quot;, 0.00) as April,
coalesce(&amp;quot;5&amp;quot;, 0.00) as May,
coalesce(&amp;quot;6&amp;quot;, 0.00) as June,
coalesce(&amp;quot;7&amp;quot;, 0.00) as July,
coalesce(&amp;quot;8&amp;quot;, 0.00) as August,
coalesce(&amp;quot;9&amp;quot;, 0.00) as September,
coalesce(&amp;quot;10&amp;quot;, 0.00) as October,
coalesce(&amp;quot;11&amp;quot;, 0.00) as November,
coalesce(&amp;quot;12&amp;quot;, 0.00) as December
from bks
pivot( sum(amount) for bmonth 
       in (&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;6&amp;quot;,&amp;quot;7&amp;quot;,&amp;quot;8&amp;quot;,&amp;quot;9&amp;quot;,&amp;quot;10&amp;quot;,&amp;quot;11&amp;quot;,&amp;quot;12&amp;quot;) ) pvt
order by &amp;quot;Sales Year&amp;quot; desc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Results will look similar to below:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/development.PivotRollingPeriodsDynamicButNot/1881.pivot_2D00_1_2D00_results.jpg"&gt;&lt;img border="0" src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/development.PivotRollingPeriodsDynamicButNot/1881.pivot_2D00_1_2D00_results.jpg" style="border:0;" alt="Pivot with Explicit Select List" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The above uses the month number, since it has to be typed multiple times as use explicit select list to use functions like coalesce(). &amp;nbsp;This is more important when doing advanced pivoting like with multiple columns (&lt;a target="_blank" title="Broaden Your Horizons : Pivot Again!" href="http://experts-exchange.com/viewArticle.jsp?aid=1537"&gt;experts-exchange.com/viewArticle.jsp?aid=1537&lt;/a&gt;); however, since we have a simple case here where null may be okay as it quickly answers the question of a missing data point versus a very poor $0.00 booking month, we can use a much simplified code:
&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;with bks(&amp;quot;Sales Year&amp;quot;, bmonthname, amount)
as
(
select year(bk_date), datename(month, bk_date), bk_amount
from bookings
where bk_date &amp;gt;= dateadd(year, datediff(year, 0, getdate())-1, 0)
)
select *
from bks
pivot( sum(amount) for bmonthname
       in (January, February, March, April, May, June,
           July, August, September, October, November, December) ) pvt
order by &amp;quot;Sales Year&amp;quot; desc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This version looks similar to this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/development.PivotRollingPeriodsDynamicButNot/6082.pivot_2D00_2_2D00_results.jpg"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/development.PivotRollingPeriodsDynamicButNot/6082.pivot_2D00_2_2D00_results.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you will see, we haven&amp;#39;t lost any value in the actual data and gained less code to maintain and a clear cut distinction between 0&amp;#39;s and no data as already stated. &amp;nbsp;We utilize the datename() function here to strip out the year and day as we did before, but instead of just a number we return full month. &amp;nbsp;For consistency, you can use left( datename( month, bk_date ), 3 ) and you will get &amp;#39;Jan&amp;#39;, &amp;#39;Feb&amp;#39;, &amp;#39;Mar&amp;#39;, etc. &amp;nbsp;It is normally not a good practice to use wilcard (*) for selecting records, but since we explicitly defined the columns we wanted in the CTE, &amp;#39;select *&amp;#39; is very safe here as we are still protected from changes in the underlying table structure as we are selecting all from the CTE and not the base table.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Notice, we still following the same syntax on the pivot, just changed the actual values in play.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;pivot( aggregate_function( column_to_aggregate ) for column_to_pivot
       in ( pivot_value1 [, pivot_value2 [, ... pivot_valuen]] )
) pivot_alias&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Hopefully that was helpful!&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This was my first entry, so hopefully you liked it. &amp;nbsp;Will work on adding more to it if folks are interested as I use these kinds of queries frequently for things like item inventory turns over or dependent / independent usage over the past 12 months, so have played with it a bit.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-- Kevin&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=283" width="1" height="1"&gt;</description><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL+2008/default.aspx">SQL 2008</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL/default.aspx">SQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/CTE/default.aspx">CTE</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/Beginner+SQL/default.aspx">Beginner SQL</category></item><item><title>Concatenating Results through SELECT statements</title><link>http://sqlservernation.com/blogs/development/archive/2009/03/20/concatenating-results-through-select-statements.aspx</link><pubDate>Fri, 20 Mar 2009 20:53:00 GMT</pubDate><guid isPermaLink="false">a3dbd76b-19b9-441f-b40a-d79e8f433d35:147</guid><dc:creator>TimChapman</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlservernation.com/blogs/development/rsscomments.aspx?PostID=147</wfw:commentRss><comments>http://sqlservernation.com/blogs/development/archive/2009/03/20/concatenating-results-through-select-statements.aspx#comments</comments><description>&lt;p&gt;In this SQL tip I am going to show you a neat little trick which involves using a simple SELECT statement to concatenate row values into a single variable value.&lt;/p&gt;
&lt;p&gt;First, I&amp;#39;ll create a temp table named #Results for which I&amp;#39;ll store FirstName and LastName data.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;IF OBJECT_ID(&amp;#39;tempdb..#Results&amp;#39;) IS NOT NULL&lt;br /&gt;    DROP TABLE #Results&lt;br /&gt;&lt;br /&gt;CREATE TABLE #Results&lt;br /&gt;(&lt;br /&gt;    FirstName varchar(25), &lt;br /&gt;    LastName varchar(25)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;GO&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script adds some names to the temp table I just created.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;INSERT INTO #Results(FirstName, LastName)&lt;br /&gt;SELECT &amp;#39;Tim&amp;#39;, &amp;#39;Chapman&amp;#39; &lt;br /&gt;UNION ALL&lt;br /&gt;SELECT &amp;#39;Brandon&amp;#39;, &amp;#39;Galderisi&amp;#39; &lt;br /&gt;UNION ALL&lt;br /&gt;SELECT &amp;#39;Aaron&amp;#39;,&amp;#39;Akin&amp;#39; &lt;br /&gt;UNION ALL&lt;br /&gt;SELECT &amp;#39;Mark&amp;#39;, &amp;#39;Wills&amp;#39; &lt;br /&gt;UNION ALL&lt;br /&gt;SELECT &amp;#39;Angel&amp;#39;,&amp;#39;Eyes&amp;#39; &lt;br /&gt;UNION ALL&lt;br /&gt;SELECT &amp;#39;Daniel&amp;#39;,&amp;#39;Wilson&amp;#39;&lt;br /&gt;&lt;br /&gt;GO&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following script does the meat of the work.&amp;nbsp; I declare a variable to hold the name values and use the variable in my SELECT statement.&amp;nbsp; The SELECT statement essentially takes every value from the #Results table and appends it to the @FullNames variable.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;DECLARE @FullNames VARCHAR(200)&lt;br /&gt;&lt;br /&gt;SELECT&lt;br /&gt;    @FullNames = ISNULL(@FullNames,&amp;#39;&amp;#39;) + LastName + &amp;#39;, &amp;#39; + FirstName + &amp;#39; &amp;#39;&lt;br /&gt;FROM #Results&lt;br /&gt;&lt;br /&gt;PRINT @FullNames&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result of printing the value in the variable is below.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;Chapman, Tim Galderisi, Brandon Akin, Aaron Wills, Mark Eyes, Angel Wilson, Daniel &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I want to add a line feed to the varaible for formatting purposes, it is easy enough to do by adding the CHAR(10) character to the variable string.&amp;nbsp; This method will insert a new line feed between each value.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;DECLARE @FullNames VARCHAR(100)&lt;br /&gt;&lt;br /&gt;SELECT&lt;br /&gt;    @FullNames = ISNULL(@FullNames,&amp;#39;&amp;#39;) + LastName + &amp;#39;, &amp;#39; + FirstName + &amp;#39; &amp;#39; + CHAR(10)&lt;br /&gt;FROM #Results&lt;br /&gt;&lt;br /&gt;PRINT @FullNames&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Printing the contents of the @FullNames variable leaves me with the following output.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-size:12px;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;"&gt;&lt;code&gt;Chapman, Tim &lt;br /&gt;Galderisi, Brandon &lt;br /&gt;Akin, Aaron &lt;br /&gt;Wills, Mark &lt;br /&gt;Eyes, Angel &lt;br /&gt;Wilson, Daniel &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=147" width="1" height="1"&gt;</description><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL/default.aspx">SQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/Intermediate+SQL/default.aspx">Intermediate SQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/Beginner+SQL/default.aspx">Beginner SQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/string+sql+variable+concatenate+temp+table+results/default.aspx">string sql variable concatenate temp table results</category></item><item><title>Nested Common Table Expressions</title><link>http://sqlservernation.com/blogs/development/archive/2009/03/18/nested-common-table-expressions.aspx</link><pubDate>Thu, 19 Mar 2009 02:03:00 GMT</pubDate><guid isPermaLink="false">a3dbd76b-19b9-441f-b40a-d79e8f433d35:141</guid><dc:creator>Aaron Akin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlservernation.com/blogs/development/rsscomments.aspx?PostID=141</wfw:commentRss><comments>http://sqlservernation.com/blogs/development/archive/2009/03/18/nested-common-table-expressions.aspx#comments</comments><description>&lt;p&gt;If you&amp;#39;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&amp;#39;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 example of a simple CTE using the AdventureWorks database that will return a list of orders.
&lt;/p&gt;
&lt;pre style="border:1px dotted #99b1ff;overflow:auto;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;"&gt;&lt;code&gt;USE AdventureWorks&lt;br /&gt;&lt;br /&gt;;WITH CTE_Orders (OrderID, OrderDate) AS&lt;br /&gt;(&lt;br /&gt;  SELECT PurchaseOrderID, OrderDate&lt;br /&gt;    FROM Purchasing.PurchaseOrderHeader h&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT * FROM CTE_Orders&lt;/code&gt;&lt;/pre&gt;
&lt;pre style="border:1px dotted #99b1ff;background-color:#f1f7fb;width:100%;font-family:courier new;"&gt;&lt;code&gt;OrderID     OrderDate&lt;br /&gt;----------- ----------&lt;br /&gt;1           2001-05-17             &lt;br /&gt;2           2001-05-17             &lt;br /&gt;3           2001-05-17             &lt;br /&gt;4           2001-05-17             &lt;br /&gt;5           2001-05-31             &lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
What isn&amp;#39;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.
&lt;/p&gt;
&lt;pre style="border:1px dotted #99b1ff;overflow:auto;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;"&gt;&lt;code&gt;;WITH CTE_OrdersDetail (OrderID, OrderDetailQty, OrderDetailAmt) AS&lt;br /&gt;(&lt;br /&gt;  SELECT PurchaseOrderID, OrderQty, LineTotal&lt;br /&gt;    FROM Purchasing.PurchaseOrderDetail&lt;br /&gt;),&lt;br /&gt;&lt;br /&gt;CTE_Orders (OrderID, OrderDate) AS&lt;br /&gt;(&lt;br /&gt;  SELECT PurchaseOrderID, OrderDate&lt;br /&gt;    FROM Purchasing.PurchaseOrderHeader h&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT o.OrderDate, SUM(od.OrderDetailQty) AS TotalOrderQty, SUM(od.OrderDetailAmt) AS TotalOrderAmt&lt;br /&gt;  FROM CTE_Orders o&lt;br /&gt;    INNER JOIN CTE_OrdersDetail od ON o.OrderID = od.OrderID&lt;br /&gt;  GROUP BY o.OrderDate&lt;br /&gt;  ORDER BY o.OrderDate&lt;/code&gt;&lt;/pre&gt;
&lt;pre style="border:1px dotted #99b1ff;background-color:#f1f7fb;width:100%;font-family:courier new;"&gt;&lt;code&gt;OrderDate  TotalOrderQty TotalOrderAmt&lt;br /&gt;---------- ------------- -------------&lt;br /&gt;2001-05-17 563           9491.518&lt;br /&gt;2001-05-31 2765          94404.303&lt;br /&gt;2002-01-14 718           39874.7685&lt;br /&gt;2002-01-15 11931         259365.2145&lt;br /&gt;2002-02-08 2768          50781.36&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
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&amp;#39;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.
&lt;/p&gt;
&lt;pre style="border:1px dotted #99b1ff;overflow:auto;background-color:#ffffcf;width:100%;font-family:courier new;max-height:400px;"&gt;&lt;code&gt;;WITH CTE_OrdersDetail (OrderID, OrderDetailQty, OrderDetailAmt) AS&lt;br /&gt;(&lt;br /&gt;  SELECT PurchaseOrderID, OrderQty, LineTotal&lt;br /&gt;    FROM Purchasing.PurchaseOrderDetail&lt;br /&gt;),&lt;br /&gt;&lt;br /&gt;CTE_Orders (OrderID, OrderDate, IsLargeOrder) AS&lt;br /&gt;(&lt;br /&gt;  SELECT PurchaseOrderID, OrderDate&lt;br /&gt;       , (&lt;br /&gt;         SELECT CASE&lt;br /&gt;                  WHEN SUM(OrderDetailQty) &amp;gt;= 100 THEN 1&lt;br /&gt;                  ELSE 0&lt;br /&gt;                END&lt;br /&gt;           FROM CTE_OrdersDetail d&lt;br /&gt;           WHERE h.PurchaseOrderID = d.OrderID&lt;br /&gt;         )&lt;br /&gt;    FROM Purchasing.PurchaseOrderHeader h&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT o.OrderDate, SUM(od.OrderDetailQty) AS TotalOrderQty&lt;br /&gt;   , SUM(od.OrderDetailAmt) AS TotalOrderAmt, SUM(o.IsLargeOrder) AS NumLargeOrders&lt;br /&gt;  FROM CTE_Orders o&lt;br /&gt;    INNER JOIN CTE_OrdersDetail od ON o.OrderID = od.OrderID&lt;br /&gt;  GROUP BY o.OrderDate&lt;br /&gt;  ORDER BY o.OrderDate&lt;/code&gt;&lt;/pre&gt;
&lt;pre style="border:1px dotted #99b1ff;background-color:#f1f7fb;width:100%;font-family:courier new;"&gt;&lt;code&gt;OrderDate  TotalOrderQty TotalOrderAmt         NumLargeOrders&lt;br /&gt;---------- ------------- --------------------- --------------&lt;br /&gt;2001-05-17 563           9491.518              1&lt;br /&gt;2001-05-31 2765          94404.303             5&lt;br /&gt;2002-01-14 718           39874.7685            1&lt;br /&gt;2002-01-15 11931         259365.2145           26&lt;br /&gt;2002-02-08 2768          50781.36              5&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
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.&lt;/p&gt;
&lt;p&gt;Aaron&lt;br /&gt;&lt;a href="http://aaronakinsql.wordpress.com" target="_blank"&gt;http://aaronakinsql.wordpress.com&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=141" width="1" height="1"&gt;</description><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL+2008/default.aspx">SQL 2008</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL/default.aspx">SQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/TSQL/default.aspx">TSQL</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/CTE/default.aspx">CTE</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/SQL+2005/default.aspx">SQL 2005</category><category domain="http://sqlservernation.com/blogs/development/archive/tags/Intermediate+SQL/default.aspx">Intermediate SQL</category></item></channel></rss>