Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 855
Jack Avatar asked Feb 19 '13 07:02

Jack


People also ask

How do you use values from previous or next rows in a SQL Server query?

SQL Server LAG() is a window function that provides access to a row at a specified physical offset which comes before the current row. In other words, by using the LAG() function, from the current row, you can access data of the previous row, or the row before the previous row, and so on.

How do I find the next row value in sql?

For example, by using the LEAD() function, from the current row, you can access data of the next row, or the row after the next row, and so on. The LEAD() function can be very useful for comparing the value of the current row with the value of the following row.

How do I find the value of old rows?

1) You can use MAX or MIN along with OVER clause and add extra condition to it. The extra condition is "ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING" which will fetch previous row value. Check this: SELECT *,MIN(JoiningDate) OVER (ORDER BY JoiningDate ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS EndDate.

How do I get last 5 entries in sql?

1 Answer. ORDER BY id ASC; In the above query, we used subquery with the TOP clause that returns the table with the last 5 records sorted by ID in descending order. Again, we used to order by clause to sort the result-set of the subquery in ascending order by the ID column.


Video Answer


2 Answers

Here is a simpler solution, still it's more efficient

SELECT P.PreviousID, N.NextID
FROM
(SELECT  MAX(D.InstrumentID) PreviousID
FROM Documents D
WHERE InstrumentID < @InstrumentID) P
CROSS JOIN
(SELECT  MIN(D.InstrumentID) NextID
FROM Documents D
WHERE InstrumentID > @InstrumentID) N
like image 178
Igor Borisenko Avatar answered Nov 15 '22 07:11

Igor Borisenko


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.

like image 30
Roman Badiornyi Avatar answered Nov 15 '22 07:11

Roman Badiornyi