有没有办法在SELECT语句中访问“上一行”值?

我需要计算一个表的两行之间的列的差异,有什么办法,我可以直接在SQL中做到这一点? 我正在使用Microsoft SQL Server 2008。

我正在寻找这样的东西:

SELECT value - (previous.value) FROM table 

设想“前一个”variables引用最近select的行。 当然,如果select这样的结果,我最终会在n行的表中selectn-1行,这不是一个可能,实际上正是我所需要的。

这在某种程度上可能吗?

SQL没有内置的命令的概念,所以你需要通过一些列命令这是有意义的。 像这样的东西:

 select t1.value - t2.value from table t1, table t2 where t1.primaryKey = t2.primaryKey - 1 

如果你知道如何sorting,而不是如何获得以前的值(EG,你想要按字母顺序排列),那么我不知道在标准SQL中这样做的方法,但是大多数SQL实现将会有扩展来做到这一点。

这是SQL服务器的一种工作方式,如果您可以对行进行sorting以使每一行都不同:

 select rank() OVER (ORDER BY id) as 'Rank', value into temp1 from t select t1.value - t2.value from temp1 t1, temp1 t2 where t1.Rank = t2.Rank - 1 drop table temp1 

如果您需要打破关系,您可以根据需要添加任意数量的列到ORDER BY。

 WITH CTE AS ( SELECT rownum = ROW_NUMBER() OVER (ORDER BY columns_to_order_by), value FROM table ) SELECT curr.value - prev.value FROM CTE cur INNER JOIN CTE prev on prev.rownum = cur.rownum - 1 

Oracle,PostgreSQL,SQL Server以及更多的RDBMS引擎都具有称为LAGLEAD分析function,可以做到这一点。

在2012年之前的SQL Server中,您需要执行以下操作:

 SELECT value - ( SELECT TOP 1 value FROM mytable m2 WHERE m2.col1 < m1.col1 OR (m2.col1 = m1.col1 AND m2.pk < m1.pk) ORDER BY col1, pk ) FROM mytable m1 ORDER BY col1, pk 

,其中COL1是您正在订购的列。

有一个索引(COL1, PK)将大大改善这个查询。

使用滞后函数:

 SELECT value - lag(value) OVER (ORDER BY Id) FROM table 

用于ID的序列可以跳过值,所以Id-1并不总是工作。

LEFT将表联接到自己,联接条件已经解决,所以在表的联接版本中匹配的行是之前的一行,用于“previous”的特定定义。

更新:起初,我想你会想保留所有的行,用NULL作为没有前一行的条件。 再读一遍,你只是想把这些行剔除,所以你应该内部连接而不是左连接。


更新:

新版本的Sql Server也有LAG和LEAD Windowing函数可以用于这个。

所选答案只有在序列中没有空白的情况下才有效。 但是,如果您正在使用自动生成的标识,则由于插入已回退,序列中可能会出现空白。

如果你有差距,这个方法应该可以工作

 declare @temp (value int, primaryKey int, tempid int identity) insert value, primarykey from mytable order by primarykey select t1.value - t2.value from @temp t1 join @temp t2 on t1.tempid = t2.tempid - 1 
 select t2.col from ( select col,MAX(ID) id from ( select ROW_NUMBER() over(PARTITION by col order by col) id ,col from testtab t1) as t1 group by col) as t2