Jack Jack - 2 months ago 7
SQL Question

How to get previous and next row's value effeciently in SQL server

Say I have these rows,

InstrumentID

547
698
708


InstrumentID is not autogenerated column.

Say if I pass the parameter in procedure as 698, I should get previous value as 547 and next value as 708. How do I do this efficiently in SQL?

I have this procedure but it is not efficient (and not correct).

Alter PROCEDURE GetNextAndPreviousInsturmentID
(
@InstrumentID varchar(14),
@PreviousInstrumentID varchar(14) OUT,
@NextInstrumentID varchar(14) OUT
)
AS
BEGIN
Declare @RowNum int = 0

Select @RowNum = ROW_NUMBER() Over (Order by Cast(@InstrumentID as decimal(18))) From Documents Where InstrumentID = @InstrumentID

;With normal As
(
Select ROW_NUMBER() Over (Order by Cast(@InstrumentID as decimal(18))) as RowNum, Cast(InstrumentID as decimal(18)) as InstrumentID
From Documents
)
Select @PreviousInstrumentID = InstrumentID From normal
Where RowNum = @RowNum - 1
Select @NextInstrumentID = InstrumentID From normal
Where RowNum = @RowNum + 1

END
GO

Answer

Try this:

Alter PROCEDURE GetNextAndPreviousInsturmentID
(
    @InstrumentID   varchar(14),
    @PreviousInstrumentID   varchar(14) OUT,
    @NextInstrumentID   varchar(14) OUT
)
AS
BEGIN

    Declare @Ids TABLE(Id varchar(14))

    ;With normal As
    (   
        --Numerate our rows
        Select ROW_NUMBER() Over (Order by Cast(Documents.InstrumentID as decimal(18)) as RowNumber,
               Documents.InstrumentID
        From Documents 

    )
    --Insert three rows from our table with our id and previos/next id
    INSERT INTO @Ids(Id)
    SELECT TOP(3) normal.InstrumentID
    FROM normal
    WHERE RowNumber >=
        (
            SELECT RowNumber - 1
            FROM normal
            WHERE normal.InstrumentID = @InstrumentID
        )
    ORDER BY normal.RowNumber
    --select next and previos ids

    SELECT @PreviousInstrumentID = Min(CAST(Id as decimal(18))),
           @NextInstrumentID = MAX(CAST(Id as decimal(18)))
    FROM @Ids
END
GO

In MS SQL 2012 we have new window functions like FIRST_VALUE and LAST_VALUE, unfortunately in sql 2008 these functions are missing.