web-dev-qa-db-ja.com

SQLで前の行を減算するにはどうすればよいですか?

現在の行を前の行から減算したい場合、何を問い合わせればよいですか。私はvb6のループで使用します。このようなもの:

Row
1
2
3
4
5

最初のループでは、前の行がないため、値1は差し引かれません。これは問題ありません。次に、次のループ値2は、値1である前の行によって差し引かれます。以下、最後の行まで続きます。

どうすればこのルーチンを達成できますか? SQLクエリまたはVB6コードによって。

13
ImTheBoss

順序付け列があると仮定すると(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()を使用します。SQLServerには「バグ」があり、coalesce()を使用すると最初の引数が2回評価されるためです。

これは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テーブルは本質的に順序付けされていないため、順序を指定する列がないと、「前の行」などはありません。

24
Gordon Linoff

カーソルの使用:

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;
0
Jorge Ribeiro