如何在 SQL Server 中有效地获取上一行和下一行的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14951682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get previous and next row's value effeciently in SQL server
提问by Hyman
Say I have these rows,
说我有这些行,
InstrumentID
仪器ID
547
698
708
InstrumentID is not autogenerated column.
InstrumentID 不是自动生成的列。
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?
假设我将过程中的参数传递为 698,我应该得到前一个值 547 和下一个值 708。我如何在 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
采纳答案by Roman Badiornyi
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.
在 MS SQL 2012 中,我们有新的窗口函数,如 FIRST_VALUE 和 LAST_VALUE,不幸的是,在 sql 2008 中这些函数丢失了。
回答by Igor Borisenko
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
回答by Radhakrishnan V
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
回答by ruisadias
select
选择
LAG(InstrumentID) OVER (ORDER BY InstrumentID) PreviousValue,
InstrumentID,
LEAD(InstrumentID) OVER (ORDER BY InstrumentID) NextValue
from documents
回答by Hasan Shouman
Hi I think this will be much more efficient:
嗨,我认为这会更有效率:
Select Next :
选择下一步:
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