﻿<?xml version='1.0' encoding='UTF-8'?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>SQLServerCentral / Article Discussions / Article Discussions by Author / Discuss content posted by Francis Rodrigues  / ROW_NUMBER(): An Efficient Alternative to Subqueries / Latest Posts</title><generator>InstantForum.NET v4.1.4</generator><description>SQLServerCentral</description><link>http://www.sqlservercentral.com/Forums/</link><webMaster>notifications@sqlservercentral.com</webMaster><lastBuildDate>Sat, 21 Nov 2009 15:02:41 GMT</lastBuildDate><ttl>20</ttl><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>I had come to this conclusion independently.  It is nice to see collaboration.One difference is that in my test case, the ROW_NUMBER was always faster even when properly indexed.  One other thing I noticed; my subquery returns ties, whereas ROW_NUMBER does not.  In order to return ties (two or more emp_id with the same comm), I used RANK() instead of ROW_NUMBER.The RANK() solution took about twice as long as the ROW_NUMBER() solution, but returned the same results as the correlated subquery.  It was still a faster solution, and the IO was much less -- create clustered index cicomm on comm(emp_id,comm desc)set statistics time onset statistics io on DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS   -- clear all data cacheDBCC FREEPROCCACHE WITH NO_INFOMSGS     -- clear stored procedure cacheprint '********************CORRELATED SUBQUERY'select * from comm awhere a.comm in (select top 3 comm from comm cq		where cq.emp_id = a.emp_id		order by comm desc ) order by emp_id, comm desc;DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS   -- clear all data cacheDBCC FREEPROCCACHE WITH NO_INFOMSGS     -- clear stored procedure cacheprint '********************ROW_NUMBER'select * from (select *, ROW_NUMBER() over(partition by emp_id order by emp_id, comm desc ) rankfrom comm) as a where rank &lt;= 3DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS   -- clear all data cacheDBCC FREEPROCCACHE WITH NO_INFOMSGS     -- clear stored procedure cacheprint '********************RANK'select * from (select *, RANK() over(partition by emp_id order by emp_id, comm desc ) rankfrom comm) as a where rank &lt;= 3Excerpt from messages:********************CORRELATED SUBQUERY(29999 row(s) affected)Table 'comm'. Scan count 430135, logical reads 1375435, physical reads 4, read-ahead reads 1119, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:   CPU time = 983 ms,  elapsed time = 1748 ms.********************ROW_NUMBER(29997 row(s) affected)Table 'comm'. Scan count 1, logical reads 1123, physical reads 4, read-ahead reads 1119, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:   CPU time = 156 ms,  elapsed time = 381 ms.********************RANK(29999 row(s) affected)Table 'comm'. Scan count 1, logical reads 1123, physical reads 3, read-ahead reads 1119, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.(1 row(s) affected) SQL Server Execution Times:   CPU time = 343 ms,  elapsed time = 567 ms.</description><pubDate>Wed, 24 Jun 2009 16:36:21 GMT</pubDate><dc:creator>bob amy</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]Pritesh Keniya (5/21/2009)[/b][hr]Thanks for introducing the concept of Row_Number(). A good example to quickly understand the concept.Just out of curiosity I thought: "What if we use CTE?"------------------------------------------------------------------------------------------------With MaxVer as (	SELECT ProductID, MAX(Version) AS Version	from Production.ProductVersion WITH (NOLOCK)	Group by ProductID),MaxMinorVer as (	Select PV.ProductID, PV.Version, MAX(MinorVersion) as MinorVersion 	From Production.ProductVersion PV WITH (NOLOCK) 	Inner Join MaxVer MV on MV.ProductID = PV.ProductID and MV.Version = PV.Version	Group by PV.ProductID, PV.Version),MaxReleaseVersion as (	Select PV.ProductID, PV.Version, PV.MinorVersion, MAX(ReleaseVersion) as ReleaseVersion 	From Production.ProductVersion PV WITH (NOLOCK) 	Inner Join MaxMinorVer MV on MV.ProductID = PV.ProductID and MV.Version = PV.Version and MV.MinorVersion = PV.MinorVersion 	Group by PV.ProductID, PV.Version, PV.MinorVersion )Select PV.* from Production.ProductVersion PVInner Join MaxReleaseVersion MV WITH (NOLOCK) on MV.ProductID = PV.ProductID and MV.Version = PV.Version 													and MV.MinorVersion = PV.MinorVersion and MV.ReleaseVersion = PV.ReleaseVersionorder by PV.ProductID-------------------------------------------------------------------------------------------------And I found out: Following is the subtree cost (CTE vs Row_Number()) for 100000 rows:CTE:                0.670628Row_Number():  5.97198Just an other approach to the example.:)[/quote]This approach is fine.  The estimate even indicates that it is faster.  One of my main goals was to show that if changes needed to be made to the code, ROW_NUMBER() offers one place for the change to be made rather than cascading through different sections.  Ultimately it is up to the programmers to decide what suits their needs the best.</description><pubDate>Thu, 21 May 2009 08:11:38 GMT</pubDate><dc:creator>Francis Rodrigues-459442</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Thanks for introducing the concept of Row_Number(). A good example to quickly understand the concept.Just out of curiosity I thought: "What if we use CTE?"------------------------------------------------------------------------------------------------With MaxVer as (	SELECT ProductID, MAX(Version) AS Version	from Production.ProductVersion WITH (NOLOCK)	Group by ProductID),MaxMinorVer as (	Select PV.ProductID, PV.Version, MAX(MinorVersion) as MinorVersion 	From Production.ProductVersion PV WITH (NOLOCK) 	Inner Join MaxVer MV on MV.ProductID = PV.ProductID and MV.Version = PV.Version	Group by PV.ProductID, PV.Version),MaxReleaseVersion as (	Select PV.ProductID, PV.Version, PV.MinorVersion, MAX(ReleaseVersion) as ReleaseVersion 	From Production.ProductVersion PV WITH (NOLOCK) 	Inner Join MaxMinorVer MV on MV.ProductID = PV.ProductID and MV.Version = PV.Version and MV.MinorVersion = PV.MinorVersion 	Group by PV.ProductID, PV.Version, PV.MinorVersion )Select PV.* from Production.ProductVersion PVInner Join MaxReleaseVersion MV WITH (NOLOCK) on MV.ProductID = PV.ProductID and MV.Version = PV.Version 													and MV.MinorVersion = PV.MinorVersion and MV.ReleaseVersion = PV.ReleaseVersionorder by PV.ProductID-------------------------------------------------------------------------------------------------And I found out: Following is the subtree cost (CTE vs Row_Number()) for 100000 rows:CTE:                0.670628Row_Number():  5.97198Just an other approach to the example.:)</description><pubDate>Thu, 21 May 2009 06:19:16 GMT</pubDate><dc:creator>Pritesh Keniya</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]wbrianwhite (5/13/2009)[/b][hr][quote][b]Mike C (5/13/2009)[/b][hr]There's always more than one way to skin a cat.  The question is twofold:  (1) What's the performance of the alternative solution and (2) is the alternative solution easier to manage?  I think the demonstration here was that the performance and manageability are both improved with CTEs and ranking/windowing functions.[/quote]But the performance of the subquery approach was actually 100% - 500% BETTER than the performance of the ROW_NUMBER() approach, when the table in question was properly indexed (and tables should always be properly indexed).  From Figure 4:[quote]Rows     - Sub     -   Row_Number()100000  - 2.2258 -   5.971981000000 -14.3881 -  83.7228[/quote]Ignoring a 100% - 500% performance improvement to use a nifty new trick is what I would consider suicidal.[/quote]When you say "properly indexed" you're referring to the clustered index on the versioning columns, correct?  I'm trying to think of situations where I would use my single clustered index per table on the versioning columns.  I think a more realistic example would be no index on the versioning columns, or nonclustered index on them in which case you might have to contend with RID lookups which can be even more expensive (unless you create covering indexes of course).</description><pubDate>Wed, 13 May 2009 22:11:21 GMT</pubDate><dc:creator>Mike C</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]Mike C (5/13/2009)[/b][hr]There's always more than one way to skin a cat.  The question is twofold:  (1) What's the performance of the alternative solution and (2) is the alternative solution easier to manage?  I think the demonstration here was that the performance and manageability are both improved with CTEs and ranking/windowing functions.[/quote]But the performance of the subquery approach was actually 100% - 500% BETTER than the performance of the ROW_NUMBER() approach, when the table in question was properly indexed (and tables should always be properly indexed).  From Figure 4:[quote]Rows     - Sub     -   Row_Number()100000  - 2.2258 -   5.971981000000 -14.3881 -  83.7228[/quote]Ignoring a 100% - 500% performance improvement to use a nifty new trick is what I would consider suicidal.</description><pubDate>Wed, 13 May 2009 14:53:46 GMT</pubDate><dc:creator>wbrianwhite</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]wbrianwhite (5/12/2009)[/b][hr]In what way was simple set logic unable to perform this operation?  It looks like this could be solved with left outer joins and is null tests.  I don't have the test db mentioned, so my &gt; may be wrong, it could need to be a &lt;, I can never remember without testing it.   But something like this should do the trick[/quote]There's always more than one way to skin a cat.  The question is twofold:  (1) What's the performance of the alternative solution and (2) is the alternative solution easier to manage?  I think the demonstration here was that the performance and manageability are both improved with CTEs and ranking/windowing functions.</description><pubDate>Wed, 13 May 2009 12:50:47 GMT</pubDate><dc:creator>Mike C</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Well, exactly. I wouldn't compare this to subqueries, I'd compare it to using top and a sort. Is it faster than that? I'd expect them to be about the same -- I don't see what Row_Number() gets us.</description><pubDate>Wed, 13 May 2009 09:30:56 GMT</pubDate><dc:creator>Ion Freeman</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]wbrianwhite (5/12/2009)[/b][hr][quote][b]William Hutton (5/12/2009)[/b][hr]I think it's just a matter of ...elegance? To me using Row_Number() statements (and CTEs in general) are easier to write and easier to follow in specific situations (provided the one reading knows what they do). And I can tell you just from testing this morning that the Row_Number() query has a performance improvement over the left joins and isnull tests I had been using previously.[/quote]Do they?  How big is it?  Is that before or after you make a clustered index on the four significant columns? In figure 4 it looks like a well-indexed table is faster when queried by the sub-query approach.  And since this table is going to be used in lots and lots of joins besides the one in the article, it needs to be well-indexed anyway. The comparison of query plans in the article is skewed because the 14 nested subqueries can be replaced by a single select with 4 left outer joins, and it is that query plan comparison I'd be interested in seeing. Also, isn't that subquery getting the max release version and standard cost as well, while the Row_Number() version is not?[/quote]The MAX release version is inherently pulled by the ORDER BY ... DESC.  The standard cost that is selected is the one that is associated with that particular minor version and release version for a product.</description><pubDate>Tue, 12 May 2009 21:13:01 GMT</pubDate><dc:creator>Francis Rodrigues-459442</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>I just tried it on my query and both of them appear to have returned the same results, so I suspect that you're correct about them being the same.</description><pubDate>Tue, 12 May 2009 16:39:44 GMT</pubDate><dc:creator>William Hutton-462896</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]William Hutton (5/12/2009)[/b][hr]I think it's just a matter of ...elegance? To me using Row_Number() statements (and CTEs in general) are easier to write and easier to follow in specific situations (provided the one reading knows what they do). And I can tell you just from testing this morning that the Row_Number() query has a performance improvement over the left joins and isnull tests I had been using previously.[/quote]Do they?  How big is it?  Is that before or after you make a clustered index on the four significant columns? In figure 4 it looks like a well-indexed table is faster when queried by the sub-query approach.  And since this table is going to be used in lots and lots of joins besides the one in the article, it needs to be well-indexed anyway. The comparison of query plans in the article is skewed because the 14 nested subqueries can be replaced by a single select with 4 left outer joins, and it is that query plan comparison I'd be interested in seeing. Also, isn't that subquery getting the max release version and standard cost as well, while the Row_Number() version is not?</description><pubDate>Tue, 12 May 2009 16:14:12 GMT</pubDate><dc:creator>wbrianwhite</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]UncleJimBob (5/12/2009)[/b][hr]I have seen similar examples of ROW_NUMBER() usage and the following has always puzzled me:Why do we include columns in the ORDER BY when they are already in the PARTITION BY ?i.e. I would expectSELECT ROW_NUMBER() OVER(PARTITION BY ProductID,                     Version ORDER BY ProductID, Version, MinorVersion DESC, ReleaseVersion DESC) AS MaxVersionto be equivalent toSELECT ROW_NUMBER() OVER(PARTITION BY ProductID,                     Version ORDER BY MinorVersion DESC, ReleaseVersion DESC) AS MaxVersionI know I must be missing obvious with this but I'm hanged if I can figure out what it is... :-)[/quote]AFAIK, you are correct.  There's no reason to include a column in the ORDER BY if it's already in the PARTITION BY, it has no effect.</description><pubDate>Tue, 12 May 2009 15:56:03 GMT</pubDate><dc:creator>RBarryYoung</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>I have seen similar examples of ROW_NUMBER() usage and the following has always puzzled me:Why do we include columns in the ORDER BY when they are already in the PARTITION BY ?i.e. I would expectSELECT ROW_NUMBER() OVER(PARTITION BY ProductID,                     Version ORDER BY ProductID, Version, MinorVersion DESC, ReleaseVersion DESC) AS MaxVersionto be equivalent toSELECT ROW_NUMBER() OVER(PARTITION BY ProductID,                     Version ORDER BY MinorVersion DESC, ReleaseVersion DESC) AS MaxVersionI know I must be missing obvious with this but I'm hanged if I can figure out what it is... :-)</description><pubDate>Tue, 12 May 2009 15:45:17 GMT</pubDate><dc:creator>UncleJimBob</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Thanks for a good article, I definitely learned what Row_Number() is - definitely had no idea before.</description><pubDate>Tue, 12 May 2009 14:52:06 GMT</pubDate><dc:creator>chill-1062987</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>I think this was a good demonstration of where these 2005+ features can be useful. I have a job coming up where this could really help.IMO, none of the few alternative queries posted so far are as clear in their intent, which I think is almost as important as performance, and an acceptable trade-off where performance isn't dramatically affected.Slightly off-topic, but I couldn't help being reminded of someone's suggestion I saw recently of a 'FIRST' aggregate (MS Access has one), which of course would make the query really simple, and probably perform really well. I suspect there must be someone who'd done one using CLR:SELECT  ProductID,     FIRST(Version) AS Version,     FIRST(MinorVersion) AS MinorVersion,     FIRST(ReleaseVersion) AS ReleaseVersion,     FIRST(StandardCost) AS StandardCostFROM Production.ProductVersionORDER BY ProductID, Version DESC, MinorVersion DESC, ReleaseVersion DESCGROUP BY ProductID</description><pubDate>Tue, 12 May 2009 14:38:30 GMT</pubDate><dc:creator>Ryan C. Price</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]wbrianwhite (5/12/2009)[/b][hr]In what way was simple set logic unable to perform this operation?  It looks like this could be solved with left outer joins and is null tests.  I don't have the test db mentioned, so my &gt; may be wrong, it could need to be a &lt;, I can never remember without testing it.   But something like this should do the trick[/quote]I think it's just a matter of ...elegance? To me using Row_Number() statements (and CTEs in general) are easier to write and easier to follow in specific situations (provided the one reading knows what they do). And I can tell you just from testing this morning that the Row_Number() query has a performance improvement over the left joins and isnull tests I had been using previously.</description><pubDate>Tue, 12 May 2009 14:35:36 GMT</pubDate><dc:creator>William Hutton-462896</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>In what way was simple set logic unable to perform this operation?  It looks like this could be solved with left outer joins and is null tests.  I don't have the test db mentioned, so my &gt; may be wrong, it could need to be a &lt;, I can never remember without testing it.   But something like this should do the trick[code]SELECT p.ProductID, p.Version, p.MinorVersion, p.ReleaseVersion, p.StandardCostfrom Production.ProductVersion pleft join Production.ProductVersion exclude1	on p.ProductID = exclude1.ProductID	and p.Version &gt; exclude1.Versionleft join Production.ProductVersion exclude2	on p.ProductID = exclude2.ProductID	and p.Version = exclude2.Version	and p.MinorVersion &gt; exclude2.MinorVersionleft join Production.ProductVersion exclude3	on p.ProductID = exclude3.ProductID	and p.Version = exclude3.Version	and p.MinorVersion = exclude3.MinorVersion	and p.ReleaseVersion &gt; exclude3.ReleaseVersionleft join Production.ProductVersion exclude4	on p.ProductID = exclude4.ProductID	and p.Version = exclude4.Version	and p.MinorVersion = exclude4.MinorVersion	and p.ReleaseVersion = exclude4.ReleaseVersion	and p.StandardCost &gt; exclude4.StandardCostwhere exclude1.Version is null	and exclude2.MinorVersion is null	and exclude3.ReleaseVersion is null	and exclude4.StandardCost is null[/code]</description><pubDate>Tue, 12 May 2009 12:31:31 GMT</pubDate><dc:creator>wbrianwhite</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]Francis Rodrigues (5/12/2009)[/b][hr]There are not any issues to my knowledge that require the NOLOCK hint for ROW_NUMBER().  I just used it for performance reasons.[/quote]Thanks for the clarification.  I guess that's what I was trying to get at.  Do you mean that ROW_NUMBER() has such bad performance that you need to resort to using NOLOCK?  Or is using NOLOCK just a common practice for your queries to try to preempt performance problems?Thanks.</description><pubDate>Tue, 12 May 2009 12:20:32 GMT</pubDate><dc:creator>JJ B</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]JJ B (5/12/2009)[/b][hr]Well done article.  Question: I hate to open a can of worms on a different topic, but I'm so curious as to why you specified the nolock hint for the row_number version of the query.  Do you know of specific problems that require use of nolock for this type of implementation?Thanks.[/quote]There aren't any problems with the ROW_NUMBER() version of the query that require the NOLOCK hint.  I just used it for the slight performance improvement.</description><pubDate>Tue, 12 May 2009 12:19:38 GMT</pubDate><dc:creator>Francis Rodrigues-459442</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>There are not any issues to my knowledge that require the NOLOCK hint for ROW_NUMBER().  I just used it for performance reasons.</description><pubDate>Tue, 12 May 2009 12:16:35 GMT</pubDate><dc:creator>Francis Rodrigues-459442</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>[quote][b]tony rogerson (5/12/2009)[/b][hr]Using non-deterministic functions like ROW_NUMBER and NEWID need to be done carefully - my blog article: http://sqlblogcasts.com/blogs/tonyrogerson/archive/2008/06/12/bug-in-inline-expansion-of-non-deterministic-functions-in-derived-tables-and-cte-s-causes-incorrect-results.aspx explains the serious bug that exists in SQL Server 2005 with using them.[/quote]Afraid that I do not understand this.  AFAIK, CTEs are table expressions like non-indexed views.  If you write them non-deterministically (which is what you do in your blog article), then they return non-deterministic results.  And if you reference a non-deterministic table expression multiple times, you are not guaranteed to get the same results.  That's straight ANSI SQL to the best of my knowledge and I see no bug in Transact-SQL demonstrated here.And as far as ROW_NUMBER() it only returns non-deterministic results if the OVER clause parameters are non-deterministic.  If you use a deterministic ORDER BY (which also requires that the column set is uniquely orderable), then you will get deterministic results.  All this really demonstrates is that if you input non-deterministic expressions without instantiating them, then you will get non-deterministic results back.  Garbage In, Garbage Out.</description><pubDate>Tue, 12 May 2009 09:43:25 GMT</pubDate><dc:creator>RBarryYoung</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Well done article.  Question: I hate to open a can of worms on a different topic, but I'm so curious as to why you specified the nolock hint for the row_number version of the query.  Do you know of specific problems that require use of nolock for this type of implementation?Thanks.</description><pubDate>Tue, 12 May 2009 09:38:06 GMT</pubDate><dc:creator>JJ B</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>How could I leverage this to get, say, the "most current" version of a contract (i.e., either the contract currently in effect or the latest contract even if it was expired) *and* the latest version of the contract (i.e., it doesn't take effect until the future? I have a  query using subqueries for this that looks something like this (this is simplified a bit). The row_number() query is much more concise but only returns that max contract date for each contract, which leaves out the current dates for those that have them:SELECT DISTINCT group_number      ,subgroup_number      ,ISNULL(        (SELECT MAX(contract_thru_date)        FROM    contracts curr1        WHERE   curr1.group_number=curr.group_number                AND GETDATE() BETWEEN contract_from_date AND contract_thru_date              ,(SELECT MAX(contract_thru_date)                FROM    contracts prev                WHERE   prev.group_number=curr.group_number                )        ) contract_thru_date FROM contracts currEDIT: NM, I figured it out. All I had to was add an or statement to the where in the CTE. Great article, came at a good time! :w00t:</description><pubDate>Tue, 12 May 2009 09:18:11 GMT</pubDate><dc:creator>William Hutton-462896</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Thanks for the great article - I thought that you did a good job of explaining how to use the row_number function and comparing its performance to subqueries.Tim</description><pubDate>Tue, 12 May 2009 08:24:09 GMT</pubDate><dc:creator>greenantim</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Nice example!Alternativly you could use a cursor to make it more readable and improve performance over a nested query. That said i dont like cursors and do prefer common table expressions![code]SET ROWCOUNT 0goIF OBJECT_ID('tempdb..#ProductVersion') IS NULLBEGIN	CREATE TABLE #ProductVersion	(		ProductID int NOT NULL,		Version int NOT NULL,		MinorVersion int NOT NULL,		ReleaseVersion int NOT NULL,		StandardCost numeric(30, 4) NOT NULL	)ENDDECLARE @ProductId INTDECLARE A CURSOR FOR	SELECT	ProductId	FROM	ProductVersion	GROUP BY ProductId	ORDER BY ProductIdOPEN AFETCH NEXT FROM A	INTO @ProductIdWHILE	@@FETCH_STATUS = 0BEGIN	INSERT INTO #ProductVersion	SELECT	TOP 1 ProductId,			Version,			MinorVersion,			ReleaseVersion,			StandardCost 	FROM	ProductVersion	WHERE	ProductId = @ProductId	ORDER BY ProductId ASC,			Version DESC,			MinorVersion DESC,			ReleaseVersion DESC	FETCH NEXT FROM A	INTO @ProductIdENDCLOSE ADEALLOCATE ASELECT * FROM #ProductVersionDROP TABLE #ProductVersion[/code]</description><pubDate>Tue, 12 May 2009 07:29:28 GMT</pubDate><dc:creator>jochemvdende</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Great Article - thank you</description><pubDate>Tue, 12 May 2009 06:22:14 GMT</pubDate><dc:creator>Jason Rogers-460518</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Other uses of Row_number() function[url]http://sqlblogcasts.com/blogs/madhivanan/archive/2007/08/27/multipurpose-row-number-function.aspx[/url]</description><pubDate>Tue, 12 May 2009 04:59:05 GMT</pubDate><dc:creator>Madhivanan-208264</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>And if you're using SQLServer2000, then you'll need to use a "TOP n" correlated subquery, since ROW_NUMBER() is not available.. eg:[quote]select RecentVersion.*from	(select distinct ProductId from dbo.ProductVersion) ProductListinner join dbo.ProductVersion RecentVersionon RecentVersion.ProductId = ProductList.ProductIdand cast(RecentVersion.Version as varchar(10)) + '.' + cast(RecentVersion.MinorVersion as varchar(10)) + '.' + cast(RecentVersion.ReleaseVersion as varchar(10)) = (select top 1 cast(x.Version as varchar(10)) + '.' + cast(x.MinorVersion as varchar(10)) + '.' + cast(x.ReleaseVersion as varchar(10))from dbo.ProductVersion xwhere x.ProductId = RecentVersion.ProductIdorder by x.Version desc, x.MinorVersion desc, x.ReleaseVersion desc)[/quote]</description><pubDate>Tue, 12 May 2009 02:19:45 GMT</pubDate><dc:creator>paul_ramster</dc:creator></item><item><title>RE: ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Using non-deterministic functions like ROW_NUMBER and NEWID need to be done carefully - my blog article: http://sqlblogcasts.com/blogs/tonyrogerson/archive/2008/06/12/bug-in-inline-expansion-of-non-deterministic-functions-in-derived-tables-and-cte-s-causes-incorrect-results.aspx explains the serious bug that exists in SQL Server 2005 with using them.Tony.</description><pubDate>Tue, 12 May 2009 01:18:34 GMT</pubDate><dc:creator>tony rogerson</dc:creator></item><item><title>ROW_NUMBER(): An Efficient Alternative to Subqueries</title><link>http://www.sqlservercentral.com/Forums/Topic714684-1545-1.aspx</link><description>Comments posted to this topic are about the item [B]&lt;A HREF="/articles/T-SQL/66512/"&gt;ROW_NUMBER(): An Efficient Alternative to Subqueries&lt;/A&gt;[/B]</description><pubDate>Mon, 11 May 2009 21:07:43 GMT</pubDate><dc:creator>Francis Rodrigues-459442</dc:creator></item></channel></rss>