2013-02-19 18 views
6

Dire che ho queste righe,Come ottenere valore precedente e successiva della riga efficientemente in SQL Server

InstrumentID

547 
698 
708 

InstrumentID non viene generato automaticamente colonna.

Dire se passo il parametro nella procedura come 698, dovrei ottenere il valore precedente come 547 e il valore successivo come 708. Come faccio a farlo in modo efficiente in SQL?

Ho questa procedura ma non è efficiente (e non è corretta).

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 

risposta

2

Prova questo:

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 Ci sono nuove funzioni finestra come FIRST_VALUE e LAST_VALUE, purtroppo in SQL 2008 queste funzioni sono mancanti.

+0

Come sarà la sua condizione di * RowNumber = ( SELEZIONA RowNumber - 1 FROM WHERE normale normal.InstrumentID = @InstrumentID ) * risultato in 3 righe? Inoltre non hai ancora memorizzato nelle variabili OUT? – Jack

+0

Mi dispiace, l'ho perso, ho aggiornato la risposta e ho anche aggiunto l'uso dei parametri OUT –

10

Ecco una soluzione più semplice, ancora è più efficiente

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 
+0

Eccellente, mi piace come si combina max (id) con 'where id Liam

-1

Ciao Penso che questo sarà molto più efficiente:

Selezionare Avanti:

select top 1 ID from mytable 
where ID >'698' 
order by ID asc 

Select Prev:

select top 1 ID from mytable 
where ID <'698' 
order by ID desc 
0
WITH CTE AS (
    SELECT rownum = ROW_NUMBER() OVER (ORDER BY p.LogDate), p.LogDate 
    FROM DeviceLogs p 
) 
SELECT prev.logdate PreviousValue, CTE.logdate, nex.logdate NextValue 
FROM CTE 
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1 
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1 

GO 
+0

In questo caso, è possibile utilizzare anche il comando OVER in SQL 2008 ... –

-1

selezionare

LAG(InstrumentID) OVER (ORDER BY InstrumentID) PreviousValue, 
InstrumentID, 
LEAD(InstrumentID) OVER (ORDER BY InstrumentID) NextValue 
from documents 
+0

L'OP ha dichiarato che questo è in MS SQL Server 2008 r2. Questa funzionalità non è arrivata fino a MS SQL Server 2012: https://msdn.microsoft.com/en-GB/library/hh213125.aspx – BeaglesEnd

Problemi correlati