OFFSET is not accepting start index

  • Hi ,

    I am having a strange issue not sure if this is MSSQL bug or mine ๐Ÿ™

    I have following simple code in my stored proc. even I have hard coded OFFSET to non zero, but it always return result from starting point 0. End limit "Fetch Next" is working perfect. Only problem is with start.

    SELECT

    *

    FROM #invoices

    ORDER BY #invoices.InvoiceDateTime ASC

    OFFSET @StartRow ROWS Fetch NEXT @EndRow ROWS ONLY;

  • declare @StartRow int = 10, @EndRow int = 10

    drop table #Temp;

    ;WITH

    n1 AS (SELECT * FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n)),

    n2 AS (SELECT n = 0 FROM n1, n1 n),

    iTally AS (SELECT n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM n2, n2 n)

    SELECT IDENTITY(int,1,1) AS ID,

    SomeDate,

    SomeJunk = CAST(NEWID() AS VARCHAR(36))

    INTO #Temp

    FROM iTally

    CROSS APPLY (SELECT SomeDate = DATEADD(MINUTE,ABS(CHECKSUM(NEWID()))%1440,DATEADD(day,n-10000,GETDATE()))) x

    ORDER BY SomeDate;

    CREATE UNIQUE CLUSTERED INDEX ucx_SomeDate ON #Temp (SomeDate);

    -- Return rows with ID 11 through 20

    -- @StartRow and @EndRow are poor names for these variables

    -- @Offset and @Batchsize might be better

    SELECT *

    FROM #Temp

    ORDER BY #Temp.SomeDate ASC

    OFFSET @StartRow ROWS

    Fetch NEXT @EndRow ROWS ONLY;

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Thank you Chris. I agree that your code is working.

    My code is working too, but problem is offset always start with 0. everything seems ok. so I asked if I need consider some other factors.

  • How are you setting @StartRow? It looks like it's not being set properly then.

    Wayne
    Microsoft Certified Master: SQL Server 2008
    Author - SQL Server T-SQL Recipes


    If you can't explain to another person how the code that you're copying from the internet works, then DON'T USE IT on a production system! After all, you will be the one supporting it!
    Links:
    For better assistance in answering your questions
    Performance Problems
    Common date/time routines
    Understanding and Using APPLY Part 1 & Part 2

  • it is setting correct ,as i have confirmed it via print

  • How about posting the entire SQL script or procedure that you are have difficulty with. From what you have posted we really can't give much of an answer.

  • Sure, here is code. I have removed some business rules, as I can't post entire code here.

    ALTER procedure [dbo].[spPayment]

    @CustomerNo int,

    @StartDate datetime,

    @EndDate datetime,

    @InvoiceNo varchar(20),

    @pageSize int =null,

    @PageNum int =null,

    @SortDirection varchar(4) = 'ASC'

    as

    begin

    --Declare Variable for pagination

    declare @Rows int,

    @StartRow int,

    @EndRow int;

    create table #inv(

    InvoiceNo varchar(20),

    CustomerPo varchar(20),

    InvoiceDateTime datetime

    );

    insert into #inv

    select

    Col1,col2,col3

    from Invoices invc with (NOLOCK)

    union

    select

    Col1,col2,col3

    from invoices2 invc2 with (NOLOCK);

    -- Setting varibale value to get count of rows

    set @rows =@@rowcount; -- Setting total Rows

    set @StartRow = (isnull(@PageSize,0)*isnull(@PageNum,1))-isnull(@PageSize,0);

    set @EndRow = @StartRow + isnull(@PageSize,@Rows);

    select @StartRow as StartRows,@EndRow as EndRows,@Rows/@PageSize as TotalPages; -- this select is showing correct startrow and endRow.

    SELECT

    *

    FROM #inv

    ORDER BY #inv.InvoiceDateTime ASC

    OFFSET @StartRow ROW Fetch FIRST @EndRow ROWS ONLY; -- this is considering @endRow , but fetching results from Offset 0

    End

  • Have you checked the data by eye to see if it's actually going to work?

    create table #inv(

    InvoiceNo varchar(20),

    CustomerPo varchar(20),

    InvoiceDateTime datetime

    );

    insert into #inv

    select

    Col1,col2,col3

    from Invoices invc with (NOLOCK)

    union

    select

    Col1,col2,col3

    from invoices2 invc2 with (NOLOCK);

    --select @StartRow as StartRows,@EndRow as EndRows,@Rows/@PageSize as TotalPages; -- this select is showing correct startrow and endRow.

    SELECT TOP 1000 *

    FROM #inv

    ORDER BY #inv.InvoiceDateTime ASC

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Yes, I have confirmed. Overall data set size in temp table is ~100k rows.

    When I set offset it terminate on EndRows , but always start from 0. e.g. if I set page size 10 and pageNumer 2. It return 20 rows instead 10.If I set EndRow 40, it return 40 records

  • thbaig (8/10/2015)


    Yes, I have confirmed. Overall data set size in temp table is ~100k rows.

    When I set offset it terminate on EndRows , but always start from 0. e.g. if I set page size 10 and pageNumer 2. It return 20 rows instead 10.If I set EndRow 40, it return 40 records

    I think you misunderstand how the ORDER BY extensions work.

    OFFSET @StartRow ROWS means "discard the first @StartRow rows"

    Fetch NEXT @EndRow ROWS ONLY means "beginning with the first row (after discarding the first @StartRow rows), return the next @EndRow rows".

    That's why I recommended you change the names of those variables. They don't match what they logically represent. @EndRow should be "@Batchsize", as it's the number of rows returned.

    @StartRow is the number of rows discarded.

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • This might help:

    DECLARE @pageSize INT, @PageNum INT

    SELECT @pageSize = 60, @PageNum = 1

    SELECT * FROM #inv ORDER BY #inv.InvoiceDateTime ASC

    OFFSET 0 ROWS FETCH FIRST 60 ROWS ONLY

    SELECT @pageSize = 60, @PageNum = 2

    SELECT * FROM #inv ORDER BY #inv.InvoiceDateTime ASC

    OFFSET 60 ROWS FETCH FIRST 60 ROWS ONLY

    SELECT @pageSize = 60, @PageNum = 3

    SELECT * FROM #inv ORDER BY #inv.InvoiceDateTime ASC

    OFFSET 120 ROWS FETCH FIRST 60 ROWS ONLY

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Thank you Chris. You are correct and initially I had same understanding, but I de-tracked ๐Ÿ™

    Thanks again

  • thbaig (8/10/2015)


    Thank you Chris. You are correct and initially I had same understanding, but I de-tracked ๐Ÿ™

    Thanks again

    No worries, I have days like that too - more as the grey hair overtakes the brown ๐Ÿ™‚

    โ€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.โ€ - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • thbaig (8/10/2015)


    Yes, I have confirmed. Overall data set size in temp table is ~100k rows.

    When I set offset it terminate on EndRows , but always start from 0. e.g. if I set page size 10 and pageNumer 2. It return 20 rows instead 10.If I set EndRow 40, it return 40 records

    Just an FYI, if you ever fail to supply a value for PageSize to the proc, you will indeed start at 0, as the variable will be set to 0 as a result.

    Steve (aka sgmunson) ๐Ÿ™‚ ๐Ÿ™‚ ๐Ÿ™‚
    Rent Servers for Income (picks and shovels strategy)

Viewing 14 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic. Login to reply