如果我想将当前行减去上一行,我应该查询什么。我将在vb6中使用它进行循环。 像这样:
Row
1
2
3
4
5
在第一个循环中,不会扣除值1,因为它没有前一行,这是可以的。 然后,下一个循环值2将被前一行(值1)扣除。依此类推,直到最后一行。
我怎样才能实现这个程序? 通过SQL查询或VB6代码。任何人都可以。
答案 0 :(得分:22)
假设您有一个订购列 - 比如id
- 那么您可以在SQL Server 2012中执行以下操作:
select col,
col - coalesce(lag(col) over (order by id), 0) as diff
from t;
在早期版本的SQL Server中,您可以使用相关子查询执行几乎相同的操作:
select col,
col - isnull((select top 1 col
from t t2
where t2.id < t.id
order by id desc
), 0)
from t
这使用isnull()
而不是coalesce()
,因为SQL Server中的“错误”在使用coalesce()
时会对第一个参数进行两次评估。
您也可以使用row_number()
:
with cte as (
select col, row_number() over (order by id) as seqnum
from t
)
select t.col, t.col - coalesce(tprev.col, 0) as diff
from cte t left outer join
cte tprev
on t.seqnum = tprev.seqnum + 1;
所有这些都假设您有一些用于指定排序的列。它可能是id
,也可能是创建日期或其他内容。 SQL表本质上是无序的,所以没有“前一行”没有指定排序的列。
答案 1 :(得分:0)
使用光标:
CREATE TABLE t (id int)
INSERT INTO t
VALUES(1)
INSERT INTO t
VALUES(2)
INSERT INTO t
VALUES(3)
INSERT INTO t
VALUES(4)
DECLARE @actual int;
DECLARE @last int;
DECLARE @sub int;
SET @last = 0;
DECLARE sub_cursor CURSOR FOR
SELECT *
FROM t OPEN sub_cursor
FETCH NEXT
FROM sub_cursor INTO @actual;
WHILE @@FETCH_STATUS = 0 BEGIN
SELECT @sub = @actual - @last print cast(@actual AS nvarchar) + '-' + cast(@last AS nvarchar) + '=' + cast(@sub AS nvarchar)
SET @last = @actual
FETCH NEXT FROM sub_cursor INTO @actual;
END
DROP TABLE t
CLOSE sub_cursor; DEALLOCATE sub_cursor;