有没有办法在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引擎都具有称为LAG
和LEAD
分析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