Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Find what is deprecated in SQL Server Denali by using sys.dm_os_performance_countersDebugging In SQL Server Denali »
    comments

    SQL Server Denali makes it much easier to do paging compared to previous versions of SQL Server. In SQL Server 2005 or 2008 you would do something like the following to skip the first 50 rows

    1. WITH cte AS (SELECT ROW_NUMBER() OVER(ORDER BY number) AS ROW,*
    2. FROM master..spt_values
    3. WHERE TYPE ='P'
    4. )
    5.  
    6. SELECT * FROM cte
    7. WHERE ROW BETWEEN 51 AND 100

    Take a look at how you do this in SQL Server Denali, it is much easier and cleaner in my opinion

    1. SELECT *
    2. FROM master..spt_values
    3. WHERE type ='P'
    4. ORDER BY number
    5. OFFSET 50 ROWS FETCH NEXT 50 ROWS ONLY;

    This syntax also works with parameters, here is the same code using a parameter for both the SQL Server Denali and 2005/2008 version.

    1. DECLARE @i int = 51;
    2.  
    3. WITH cte AS (SELECT ROW_NUMBER() OVER(ORDER BY number) AS ROW,*
    4. FROM master..spt_values
    5. WHERE TYPE ='P'
    6. )
    7.  
    8. SELECT * FROM cte
    9. WHERE ROW BETWEEN @i AND (@i * 2) -1
    1. DECLARE @i int = 50
    2.  
    3. SELECT *
    4. FROM master..spt_values
    5. WHERE type ='P'
    6. ORDER BY number
    7. OFFSET @i ROWS FETCH NEXT  @i ROWS ONLY;

    If you want all rows after skipping the first 50 rows, you would do something like this in a version pre SQL Server Denali

    1. DECLARE @i int = 51;
    2.  
    3. WITH cte AS (SELECT ROW_NUMBER() OVER(ORDER BY number) AS ROW,*
    4. FROM master..spt_values
    5. WHERE TYPE ='P'
    6. )
    7.  
    8. SELECT * FROM cte
    9. WHERE ROW >= @i

    In SQL Server Denali it becomes very simple, all you need to do is OFFSET N ROWS

    1. DECLARE @i int = 50
    2.  
    3. SELECT *
    4. FROM master..spt_values
    5. WHERE type ='P'
    6. ORDER BY number
    7. OFFSET @i ROWS;

    So that was just a quick look at OFFSET.
    Click on the SQL Server Denali tag to see all our SQL Server Denali related posts

    About the Author

    User bio imageDenis has been working with SQL Server since version 6.5. Although he worked as an ASP/JSP/ColdFusion developer before the dot com bust, he has been working exclusively as a database developer/architect since 2002. In addition to English, Denis is also fluent in Croatian and Dutch, but he can curse in many other languages and dialects (just ask the SQL optimizer) He lives in Princeton, NJ with his wife and three kids.
    Social SitingsTwitterFacebookLinkedInHomePageFlickrLTD RSS Feed
    2869 views
    Instapaper

    4 comments

    Comment from: Michael J Swart [Visitor] · http://michaeljswart.com/
    Michael J Swart It's cleaner syntax that's for sure. Does it have nicer execution plans?
    11/09/10 @ 12:38
    Comment from: SQLDenis [Member] Email
    SQLDenis I will modify and post the execution plans tonight
    11/09/10 @ 12:43
    Comment from: SQLDenis [Member] Email
    SQLDenis Here is what happens

    Table 'spt_values'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0

    Table 'spt_values'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0

    Row_number
    |--Filter(WHERE:([Expr1003]>=CONVERT_IMPLICIT(bigint,[@i],0) AND [Expr1003]<=CONVERT_IMPLICIT(bigint,[@i]*(2)-(1),0)))
    |--Top(TOP EXPRESSION:(CASE WHEN CONVERT_IMPLICIT(bigint,[@i]*(2)-(1),0) IS NULL OR CONVERT_IMPLICIT(bigint,[@i]*(2)-(1),0)<(0) THEN (0) ELSE CONVERT_IMPLICIT(bigint,[@i]*(2)-(1),0) END))
    |--Sequence Project(DEFINE:([Expr1003]=row_number))
    |--Segment
    |--Clustered Index Seek(OBJECT:([master].[dbo].[spt_values].[spt_valuesclust]), SEEK:([master].[dbo].[spt_values].[type]=N'P') ORDERED FORWARD)


    Offset
    |--Top(OFFSET EXPRESSION:(CONVERT_IMPLICIT(bigint,[@i],0)),TOP EXPRESSION:(CONVERT_IMPLICIT(bigint,[@i],0)))
    |--Clustered Index Seek(OBJECT:([master].[dbo].[spt_values].[spt_valuesclust]), SEEK:([master].[dbo].[spt_values].[type]=N'P') ORDERED FORWARD)
    11/09/10 @ 18:20
    Comment from: Pradeep [Visitor]
    Pradeep MYSQL alreasy has these features since 2004. Thanks to Microsoft...atleast they introduced them in 2011.
    10/01/11 @ 01:03

    Leave a comment


    Your email address will not be revealed on this site.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)