如何减去sql中的前一行?

时间:2013-07-10 01:04:53

标签: sql-server vb6

如果我想将当前行减去上一行,我应该查询什么。我将在vb6中使用它进行循环。 像这样:

Row
1
2
3
4
5

在第一个循环中,不会扣除值1,因为它没有前一行,这是可以的。 然后,下一个循环值2将被前一行(值1)扣除。依此类推,直到最后一行。

我怎样才能实现这个程序? 通过SQL查询或VB6代码。任何人都可以。

2 个答案:

答案 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;