<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlservernation.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">BrandonGalderisi</title><subtitle type="html">Covers topics that don&amp;#39;t fit into the How-Tos section.</subtitle><id>http://sqlservernation.com/blogs/brandongalderisi/atom.aspx</id><link rel="alternate" type="text/html" href="http://sqlservernation.com/blogs/brandongalderisi/default.aspx" /><link rel="self" type="application/atom+xml" href="http://sqlservernation.com/blogs/brandongalderisi/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.40407.4157">Community Server</generator><updated>2009-03-15T00:27:00Z</updated><entry><title>Development Environment Isolation</title><link rel="alternate" type="text/html" href="/blogs/brandongalderisi/archive/2009/11/17/development-environment-isolation.aspx" /><id>/blogs/brandongalderisi/archive/2009/11/17/development-environment-isolation.aspx</id><published>2009-11-18T03:03:00Z</published><updated>2009-11-18T03:03:00Z</updated><content type="html">&lt;p&gt;One of the challenges facing many development organizations is how to provide adequate development needs while providing enough isolation to prevent developer conflicts.&amp;nbsp; Today&amp;#39;s virtual technology provides the ability to spin up developer specific environments quickly easily while providing the horsepower to mimic near physical environment capacity.&amp;nbsp; I will leave the discussions over physical vs. virtual to discuss in another area, I will just talk about my recent experience, and how handling our environment differently could have yielded a more pleasurable result.&lt;/p&gt;
&lt;p&gt;First I will tell you a little bit about how we work.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;We heavily utilize virtual environments for our development and testing.&amp;nbsp; We buy high end hardware and run on high end SAN solutions.&amp;nbsp; I don&amp;#39;t know all of the details about it, I just know that it works and our SEs (System Engineers) bust their butts to give us what we need.&amp;nbsp; Our old development and QA environments are based on some variation of &lt;a target="_blank" title="VMWare" href="http://www.vmware.com/"&gt;VMWare&lt;/a&gt;.&amp;nbsp; Again, I don&amp;#39;t know what it is except that it&amp;#39;s virtual hardware and it meets our needs.&amp;nbsp; We need an environment, we ask, they deliver.&amp;nbsp; We are in the process of migrating all of our virtual systems for development and QA to a &lt;a target="_blank" title="VMWare Lab Manager" href="http://www.vmware.com/products/labmanager/"&gt;VMWare Lab Manager&lt;/a&gt; environment in a different data center.&amp;nbsp; It provides the ability to spin up groups of isolated environments, clone environments to a new configuration and much more.&amp;nbsp; I won&amp;#39;t go into the details about &lt;a target="_blank" title="VMWare Lab Manager" href="http://www.vmware.com/products/labmanager/"&gt;VMWare Lab Manager&lt;/a&gt; but our SEs have handed over the power to us to be able to create our own virtual environments as we need.&amp;nbsp; They have also provided is with over 9TB (and growing) of storage per team location to host the machines. Unfortunately we are not 100% live on this environment because we have terabytes of data to move across the WAN to the new data center.&lt;/p&gt;
&lt;p&gt;So here is what happened recently, and how things could have been different had we been completely migrated to our new &lt;a target="_blank" title="VMWare Lab Manager" href="http://www.vmware.com/products/labmanager/"&gt;VMWare Lab Manager&lt;/a&gt; environment.&lt;/p&gt;
&lt;p&gt;I was working on diagnosing a problem with deadlocks that was happening in our QA environment.&amp;nbsp; Our QA environments are well protected environments in that our developers, which I am one of, do not have administrative privileges over the web, file, database or any other servers.&amp;nbsp; Our QA teams manage them and we are limited to a basically read only access.&amp;nbsp; So when it comes time to replicating problems found in QA we must do it in our development environment.&amp;nbsp; Had this environment been in our &lt;a target="_blank" title="VMWare Lab Manager" href="http://www.vmware.com/products/labmanager/"&gt;VMWare Lab Manager&lt;/a&gt; environment, I would have been able to snapshot the QA environment, make myself an admin over the environment, and proceed with reproducing the errors.&amp;nbsp; Unfortunately it was not so I proceeded to locate an environment with the closest configuration and the same or more data.&amp;nbsp; Since we are not fully live on our new environment, all of our larger development and test environments are in our old system where we do not have abilities to clone configurations.&amp;nbsp; I contacted the person who managed the environment I had been developing on a few weeks prior in order to determine the status of the setup.&amp;nbsp;  I informed them that I needed to do extensive testing and would be doing large amounts of data manipulations to the system for troubleshooting a problem with the project that the system was originally setup to develop and test on.&amp;nbsp; I was told that the environment was scheduled for decommission two days from now and that it was not in use. I did not need to backup the database since it was scheduled for decommission, and I would only be working with 4-5 tables with under a billion records which I would be truncating in order to test the process which was deadlocking.&amp;nbsp; Due to the size of the database (100GB+) and the low amounts of storage capacity in our old environment, I likely would not have been able to backup the database if I had tried.&lt;/p&gt;
&lt;p&gt;After receiving the all clear, I connected to the system, truncated the tables which I would be working with and started my testing.&amp;nbsp; It didn&amp;#39;t take long to reproduce the problem and I was happy.&amp;nbsp; The environment had served it&amp;#39;s EXACT purpose to me.&amp;nbsp; As I was adjusting the code to eliminate the deadlocks, the person that I had received permission to use the environment stopped by my desk.&amp;nbsp; They asked, in a troubling voice, &amp;quot;are you working on the ________ environment&amp;quot;.&amp;nbsp; Puzzled, since I had just asked for permission less than two hours ago, I replied &amp;quot;Uhhh... yeah.&amp;nbsp; We just talked about that two hours ago&amp;quot;.&amp;nbsp; Well APPARENTLY the system was not quite as &amp;quot;not in use&amp;quot; as they had believed.&amp;nbsp; The system has been used for the past two weeks to do large scale testing.&amp;nbsp; Testing that was scheduled to complete the next day and full reports to be generated.&amp;nbsp; &lt;i&gt;&lt;b&gt;Unfortunately&lt;/b&gt;&lt;/i&gt;, my testing required that the very tables that were used to calculate the results of the scale testing be truncated to perform my tests.&amp;nbsp; Two weeks of testing, &lt;i&gt;&lt;b&gt;POOF GONE&lt;/b&gt;&lt;/i&gt; in less than 5 minutes.&lt;/p&gt;
&lt;p&gt;How could this disaster have been prevented?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I could have (attempted to) backup the database&lt;/li&gt;
&lt;li&gt;If successful I could have copied that database to the new environment for testing&lt;/li&gt;
&lt;li&gt;I could have looked through the database to look and see how recently it had been used through some of the logging tables (there are several)&lt;/li&gt;
&lt;li&gt;I could have found a different environment, which may have ended in the same result with a different team&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How will &lt;a target="_blank" title="VMWare Lab Manager" href="http://www.vmware.com/products/labmanager/"&gt;VMWare Lab Manager&lt;/a&gt; prevent this in the future?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rather than taking over the environment I could have cloned it to a new fenced environment where my changes would not impact any other developer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pretty simple!&lt;/p&gt;
&lt;p&gt;In closing, I do not place blame on any one person for this.&amp;nbsp; There are things that could, and should, have been done that could have prevented this.&amp;nbsp; I certainly accept part of the blame because there are things that I could have done to ensure the environment was actually unused before proceeding with my testing.&amp;nbsp; And virtualization is just one solution for preventing this type of scenario from happening.&amp;nbsp; And it may not be the solution for your organization.&amp;nbsp; But whatever your needs may be, make sure that you take the proper precautions to ensure that your development environments are isolated in such a way that developers to not wreak havoc on other developers efforts.&amp;nbsp; Work with your boss, your IT staff and the other developers to create a productive environment that meets your needs.&amp;nbsp; Document your configurations so that when the question is asked &amp;quot;Who is using this server/database/file&amp;quot; it can be easily answered.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Brandon Galderisi&lt;br /&gt;SQL Server MVP&lt;br /&gt;SQL Server Nation Co-Founder&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=325" width="1" height="1"&gt;</content><author><name>BrandonGalderisi</name><uri>http://sqlservernation.com/members/BrandonGalderisi/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Beginner+SQL/default.aspx" /><category term="Advanced SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Advanced+SQL/default.aspx" /><category term="Development" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Development/default.aspx" /><category term="Virtualization" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Virtualization/default.aspx" /></entry><entry><title>Using row_number() vs. a correlated sub-select</title><link rel="alternate" type="text/html" href="/blogs/brandongalderisi/archive/2009/09/20/using-row-number-vs-a-correlated-sub-select.aspx" /><id>/blogs/brandongalderisi/archive/2009/09/20/using-row-number-vs-a-correlated-sub-select.aspx</id><published>2009-09-21T03:40:00Z</published><updated>2009-09-21T03:40:00Z</updated><content type="html">&lt;p&gt;In this article, I will show you the differences in using the row_number() function versus a correlated sub-select for filtering data. &lt;/p&gt;
&lt;p&gt;One thing that I have seen frequently is the use of the row_number() function to limit result sets.&amp;nbsp; While row_number() has it&amp;#39;s uses, using it to filter results is not necessarily one of them.&amp;nbsp; There are several scenarios in which this is useful.&amp;nbsp; Before setting up the test data and reviewing the results, I will explain a few scenarios that I have seen.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Scenario 1&lt;br /&gt;&lt;/b&gt;I have a table that contains customer transactions.&amp;nbsp; I want to show the most recent transaction for ALL customers.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Scenario 2&lt;/b&gt;&lt;br /&gt;I havea table that contains patient doctor visits.&amp;nbsp; I want to show the most recent visit for ALL patients.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Scenario 3&lt;/b&gt;&lt;br /&gt;I run an auction site.&amp;nbsp; Show me the highest prices that each item has ever sold for.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;See the trend?&amp;nbsp; The goal is show me a specific value for every item.&amp;nbsp; For this example, we will use the patient visit scenario.&amp;nbsp; First let&amp;#39;s setup the table and some sample data.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;create table patient_visits_ADSFG&lt;br /&gt;     (patient_visit_id        int identity primary key clustered&lt;br /&gt;     ,patient_name            varchar(20) not null&lt;br /&gt;     ,visit_date              datetime not null&lt;br /&gt;     ,diagnosis_code          int null&lt;br /&gt;     ,visit_cost              money null&lt;br /&gt;     )&lt;br /&gt;GO&lt;br /&gt;;with a as&lt;br /&gt;     (select 1 as n union all select 1)&lt;br /&gt;     ,b as (select 1 as n from a as a1 ,a as a2)&lt;br /&gt;     ,c as (select 1 as n from b as b1 ,b as b2)&lt;br /&gt;     ,d as (select 1 as n from c as c1 ,c as c2)&lt;br /&gt;     ,e as (select 1 as n from d as d1 ,d as d2)&lt;br /&gt;     ,ns as (select row_number() over (order by n) as num from e)&lt;br /&gt;insert into patient_visits_ADSFG(patient_name,visit_date)&lt;br /&gt;select distinct a.b,dateadd(d, -(num*rand(checksum(newid()))),getdate())&lt;br /&gt;from ns&lt;br /&gt;cross join (select 11 a,&amp;#39;Bob&amp;#39; b&lt;br /&gt;     union select 2,&amp;#39;Brandon&amp;#39;&lt;br /&gt;     union select 3.5,&amp;#39;Jim&amp;#39;&lt;br /&gt;     union select 40,&amp;#39;Tim&amp;#39;&lt;br /&gt;     union select 23,&amp;#39;Jason&amp;#39;&lt;br /&gt;&lt;br /&gt;     ) a&lt;br /&gt;GO&lt;br /&gt;update patient_visits_ADSFG&lt;br /&gt;set diagnosis_Code = rand(patient_visit_id)&lt;br /&gt;,visit_cost=patient_visit_id+rand(patient_visit_id)&lt;br /&gt;GO&lt;br /&gt;create index idx_1 on patient_visits_ADSFG (patient_name,visit_date)&lt;br /&gt;GO&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Our goal is to show the most recent visit for each patient.&amp;nbsp; Now we know that we want to get back 5 records because we have 5 patients.&amp;nbsp; Below are two SQL statements.&amp;nbsp; Let&amp;#39;s run them and compare the execution plans.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;select patient_name,visit_date,diagnosis_code,visit_cost&lt;br /&gt;from patient_visits_ADSFG a1&lt;br /&gt;where visit_date = (select max(visit_date) &lt;br /&gt;                    from patient_visits_ADSFG &lt;br /&gt;                    where patient_name = a1.patient_name)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;;with max_patients as&lt;br /&gt;(select patient_name,visit_date,diagnosis_code,visit_cost&lt;br /&gt;     ,row_number() over (partition by patient_name &lt;br /&gt;                         order by visit_date desc) rn&lt;br /&gt; from patient_visits_ADSFG)&lt;br /&gt;select patient_name,visit_date,diagnosis_code,visit_cost&lt;br /&gt;from max_patients&lt;br /&gt;where rn=1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here are the execution plans for the above two queries.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.2009.09.21.max_5F00_vs_5F00_row_5F00_number_28002900_/8168.eplan1.jpg"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.2009.09.21.max_5F00_vs_5F00_row_5F00_number_28002900_/8168.eplan1.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.2009.09.21.max_5F00_vs_5F00_row_5F00_number_28002900_/3858.eplan2.jpg"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.2009.09.21.max_5F00_vs_5F00_row_5F00_number_28002900_/3858.eplan2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, the execution plans indicate that the first query takes 4% of the time while the second took 96%.&amp;nbsp; While both queries ran rather fast against the 163K records that the above sample generated, the first being 24 times faster is significant.&amp;nbsp; Imagine how this will scale in large environments where tables contain millions of records.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Why the difference?&lt;br /&gt;&lt;/b&gt;The reason for the difference is simple.&amp;nbsp; The first query does an index scan to find the largest date value for each patient.&amp;nbsp; The second query does an index scan and then for each patient, orders EVERY record on the visit_date descending only to filter out every value but the first.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=286" width="1" height="1"&gt;</content><author><name>BrandonGalderisi</name><uri>http://sqlservernation.com/members/BrandonGalderisi/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Beginner+SQL/default.aspx" /><category term="Advanced SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Advanced+SQL/default.aspx" /><category term="sub-select" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/sub-select/default.aspx" /><category term="row_number()" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/row_5F00_number_28002900_/default.aspx" /></entry><entry><title>What are instances?</title><link rel="alternate" type="text/html" href="/blogs/brandongalderisi/archive/2009/03/27/what-are-instances.aspx" /><id>/blogs/brandongalderisi/archive/2009/03/27/what-are-instances.aspx</id><published>2009-03-27T20:01:00Z</published><updated>2009-03-27T20:01:00Z</updated><content type="html">&lt;p&gt;Any installation of SQL Server is an instance.&amp;nbsp; There are two types of instances.&amp;nbsp; Default instances and Named instances.&amp;nbsp; Any one host computer may have many named instances of SQL Server but only one Default instance can exist.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The Default instance of SQL Server does NOT have a name.&amp;nbsp; It is not named the default instance, it just is the default instance.&amp;nbsp; The default instance is accessed by entering in the machine name into the connection.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Named instances are named and must be accessed with the instance name.&amp;nbsp; The instance name could be a reference to the version of SQL Server, or even the particular application that it is being used for.&amp;nbsp; Named instances are access by entering the machine name and the instance name into the connection information.&lt;/p&gt;
&lt;p&gt;For example, if you have an existing SQL Server running SQL Server 2005 as the default instance, and you need to install SQL Server 2008, you could name the instance SQL2008.&amp;nbsp; You would then connect to the SQL 2008 instance by entering &amp;quot;SERVERNAME\SQL2008&amp;quot; as the server in the connection information.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It is also not unreasonable to install multiple instances of the same version of SQL Server.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Reasons for installing multiple instances can include, but is not limited to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Needing to lock down a set of databases.&lt;/li&gt;
&lt;li&gt;Needing to run different global server options..&lt;/li&gt;
&lt;li&gt;A particular application needs to run on a later SQL Service Pack and other applications are not compatible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Instances are a great feature of SQL Server and can help you customize your environment to ensure maximum compatibility and flexibility.&amp;nbsp; But be aware of the downside of overloading instances.&amp;nbsp; The SQL Server Engine itself consumes system resources to manage your databases.&amp;nbsp; If you add multiple Instances, then you will have multiple Master, MSDB and Model databases.&amp;nbsp; Planning for disaster recovery becomes more complex.&amp;nbsp; And since each Instance it it&amp;#39;s own installation of SQL Server, each intance must be patched independant of others (even though most patches will allow you to select one or more instance to apply to).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=169" width="1" height="1"&gt;</content><author><name>BrandonGalderisi</name><uri>http://sqlservernation.com/members/BrandonGalderisi/default.aspx</uri></author><category term="Instances" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Instances/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Beginner+SQL/default.aspx" /></entry><entry><title>When ordering in a view doesn't work!</title><link rel="alternate" type="text/html" href="/blogs/brandongalderisi/archive/2009/03/15/when-ordering-in-a-view-doesn-t-work.aspx" /><id>/blogs/brandongalderisi/archive/2009/03/15/when-ordering-in-a-view-doesn-t-work.aspx</id><published>2009-03-15T04:27:00Z</published><updated>2009-03-15T04:27:00Z</updated><content type="html">&lt;p&gt;If I&amp;#39;ve seen it one time, I&amp;#39;ve seen it a hundred times.&amp;nbsp; People
trying to sort views by selecting 100 PERCENT in a view with an order
by.&amp;nbsp; Because after all, if you try to use an order by statement,
without a TOP statement, you will get the following error.&lt;/p&gt;
&lt;p&gt;
&lt;span style="color:red;"&gt;
&lt;p&gt;Msg 1033, Level 15, State 1, Procedure vw_CF7D3A8E67D749B38ED6E6F579AB6FF3_3, Line 4&lt;br /&gt;The
ORDER BY clause is invalid in views, inline functions, derived tables,
subqueries, and common table expressions, unless TOP or FOR XML is also
specified.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So how do you solve it?&amp;nbsp; You add TOP 100 PERCENT right?&amp;nbsp; Wrong.&amp;nbsp; It doesn&amp;#39;t work, and I&amp;#39;ll show you why.&lt;/p&gt;
&lt;p&gt;The first thing we will do is create a table to test with.&amp;nbsp; If the
name looks strange, that&amp;#39;s because I want to do my best to ensure that
there won&amp;#39;t be a name conflct with any tables in any database you may
run this in.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;create table CF7D3A8E67D749B38ED6E6F579AB6FF3&lt;br /&gt;     (a   int identity primary key clustered&lt;br /&gt;     ,b   int not null&lt;br /&gt;     ,c   char(1) not null&lt;br /&gt;     )&lt;br /&gt;go&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we will populate it with seed data and select it without an order by statement.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (1,&amp;#39;a&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (2,&amp;#39;a&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (3,&amp;#39;a&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (1,&amp;#39;b&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (2,&amp;#39;b&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (3,&amp;#39;b&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (1,&amp;#39;c&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (2,&amp;#39;c&amp;#39;)&lt;br /&gt;insert into CF7D3A8E67D749B38ED6E6F579AB6FF3 (b,c) values (3,&amp;#39;c&amp;#39;)&lt;br /&gt;go&lt;br /&gt;select * from CF7D3A8E67D749B38ED6E6F579AB6FF3&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see from the results below, with no other alterations or
indexes on the table, the results will be ordered by the clustered
index (a).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_1.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_1.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we will create two views.&amp;nbsp; The first one will select 100 PERCENT
of the records and the second one will select 99 PERCENT.&amp;nbsp; The result
here will be that the second view will still select all 9 records.&amp;nbsp; The
point is just to show the difference in sorting.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;create view vw_CF7D3A8E67D749B38ED6E6F579AB6FF3_1&lt;br /&gt;as&lt;br /&gt;select top (100) percent * from CF7D3A8E67D749B38ED6E6F579AB6FF3&lt;br /&gt;order by b&lt;br /&gt;go&lt;br /&gt;create view vw_CF7D3A8E67D749B38ED6E6F579AB6FF3_2&lt;br /&gt;as&lt;br /&gt;select top (99) percent * from CF7D3A8E67D749B38ED6E6F579AB6FF3&lt;br /&gt;order by b&lt;br /&gt;go&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now there are two ways to show you that the first view above is
invalid.&amp;nbsp; The first is to look at the results of the two statements.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;select * from vw_CF7D3A8E67D749B38ED6E6F579AB6FF3_1&lt;br /&gt;go&lt;br /&gt;select * from vw_CF7D3A8E67D749B38ED6E6F579AB6FF3_2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The first result set you will see below is the result of the first
view.&amp;nbsp; The one with TOP 100 PERCENT.&amp;nbsp; As you can see, it is still
sorted by the &amp;quot;A&amp;quot; column, the clustered index, whereas the second
result is actually sorted by column B as we told it to?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_3.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_3.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_4.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_4.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But why is that? We told it to sort by column B.&amp;nbsp; Let&amp;#39;s look at the execution plans for the two selects.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_2.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_2.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_5.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_5.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, there is no SORT happening in the first execution
plan.&amp;nbsp; The reason is that SQL Server determines that it doesn&amp;#39;t need to
sort the records in order to get the TOP 100 PERCENT of records because
ALL records are being selected.&amp;nbsp; The only time when SQL Server will
sort records in a view, is when it is necessary to do so because not
all records will be returned.&amp;nbsp; And even though in THIS case &amp;quot;TOP 99
PERCENT&amp;quot; will return all records, that won&amp;#39;t always be true so SQL
Server will sort the records to be sure.&lt;/p&gt;
&lt;p&gt;There is however a workaround.&amp;nbsp; You can use a &lt;a title="Table Valued Function" href="http://sqlservernation.com/blogs/howtos/archive/2009/03/07/table-valued-functions.aspx"&gt;Table Valued Function&lt;/a&gt; that sorts the records.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;create function dbo.fn_CF7D3A8E67D749B38ED6E6F579AB6FF3()&lt;br /&gt;returns @Res table &lt;br /&gt;     (i int identity&lt;br /&gt;     ,a int &lt;br /&gt;     ,b int&lt;br /&gt;     ,c char(1)&lt;br /&gt;     )&lt;br /&gt;as&lt;br /&gt;begin&lt;br /&gt;insert into @Res(a,b,c)&lt;br /&gt;select a,b,c from CF7D3A8E67D749B38ED6E6F579AB6FF3 &lt;br /&gt;order by b&lt;br /&gt;return&lt;br /&gt;end&lt;br /&gt;go&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now when we select the columns from the function.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;select a,b,c from dbo.fn_CF7D3A8E67D749B38ED6E6F579AB6FF3()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You will see that the results are sorted just like we wanted.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlservernation.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_4.png"&gt;&lt;img src="http://sqlservernation.com/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/brandongalderisi.when+ordering+in+a+view+doesnt+work/res_5F00_4.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;While this simple example shows a workaround for sorting in views, it is not always the right thing to do.&amp;nbsp; Selecting large data sets can hinder performance due to the amound of time it takes to copy the data into the table variable.&amp;nbsp; But when all else fails, it will get the job done!&lt;/p&gt;
&lt;p&gt;To download all of the SQL in this post, click &lt;a title="SQL Download" href="http://sqlservernation.com/media/p/109.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=107" width="1" height="1"&gt;</content><author><name>BrandonGalderisi</name><uri>http://sqlservernation.com/members/BrandonGalderisi/default.aspx</uri></author><category term="Views" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Views/default.aspx" /><category term="User Defined Functions" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/User+Defined+Functions/default.aspx" /><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Intermediate+SQL/default.aspx" /><category term="Table Valued Function" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/Table+Valued+Function/default.aspx" /><category term="order by" scheme="http://sqlservernation.com/blogs/brandongalderisi/archive/tags/order+by/default.aspx" /></entry></feed>