繁体   English   中英

将前一行值减去当前行并按日期排序

[英]Subtract previous row value to current row and order by date

我表中的数据如下

SELECT ID, VALUE, acc_no, adate 
FROM TB_DailyStatement

   id    value   acc_no       adate
    ---------------------------------------------
    1     12     1      2019-01-01 07:40:38.250
    2     14     1      2019-01-02 07:41:05.883
    3     15     1      2019-01-13 07:41:22.377
    4     10     2      2019-01-14 08:15:53.403
    5     16     2      2019-01-03 13:52:47.347 
    6     19     1      2019-01-09 13:53:56.317
    7      7     3      2019-01-17 00:00:00.000
    8     24     2      2019-01-17 00:00:00.000
    9     19     2      2019-01-02 00:00:00.000
    10     7     1      2019-01-07 00:00:00.000
    11    24     1      2019-01-05 14:12:47.080
    12    20     3      2019-01-28 00:00:00.000

预期结果

    id     value   acc_no       aDATE                   result 
    ------------------------------------------------------------------------
    1     12     1        2019-01-01 07:40:38.250        12 (current row values of acc_no=1) 
    2     14     1        2019-01-02 07:41:05.883         2 (14 (current row values)-12(previous row value of acc_no=1))  
   11     24     1        2019-01-05 14:12:47.080        10 (24 (current row values)-14(previous date  value of acc_no=1))  
   10      7     1        2019-01-07 00:00:00.000       -17 (7 (current row values)-24(previous date  value of acc_no=1))  
    6     19     1        2019-01-09 13:53:56.317        12 (19 (current row values)-7(previous date  value of acc_no=1))  
    3     15     1        2019-01-13 07:41:22.377        -4 (15 (current row values)-19(previous date  value of acc_no=1))  
    9     19     2        2019-01-02 00:00:00.000        19 (12 (current row values of acc_no=2) 
    5     16     2        2019-01-03 13:52:47.347        -3 (16 (current row values)-14(previous date  value of acc_no=2))  
    4     10     2        2019-01-14 08:15:53.403        -6 (10 (current row values)-16(previous date  value of acc_no=2))  
    8     24     2        2019-01-17 00:00:00.000        14 (24 (current row values)-10(previous date  value of acc_no=2))  
    7      7     3        2019-01-17 00:00:00.000         7 (12(current row values of acc_no=3) 
   12     20     3        2019-01-28 00:00:00.000        13 (20 (current row values)-7(previous date  value of acc_no=3)) 

我尝试了以下查询

SELECT 
    id, t.value, acc_no, adate, 
    t.value - ISNULL(v.value, 0) AS result 
FROM 
    TB_DailyStatementt
OUTER APPLY 
    (SELECT TOP (1) value
     FROM TB_DailyStatement
     WHERE id < t.id
       AND acc_no = t.acc_no
     ORDER by id DESC) v

这将返回一些输出,但是我无法使用order by子句,即adate和acc_no

如果您想通过acc_no asc简单地得到此结果,则可以得到简单的预期结果,

例如

从表顺序中按acc_no acs选择*

SQL Server 2008 ,不能使用LEAD & LAG ,为此,您可以像使用OUTER APPLY一样使用查询。

select * 
from  TB_DailyStatementt tout 
       outer apply (select top 1 value Prev 
                    from   TB_DailyStatementt t1 
                    where  t1.acc_no = tout.acc_no 
                           AND t1.adate < tout.adate 
                    order  by t1.adate desc)t1 
       outer apply (select top 1 value Next 
                    from   TB_DailyStatementt  t1 
                    where  t1.acc_no = tout.acc_no 
                           AND t1.adate > tout.adate 
                    order by t1.adate asc)t2 
       order by tout.adate,acc_no

这将根据acc_no提供所需的上一个和下一个值。 现在,您可以应用开关大小写来格式化字符串。

检查这个演示

Declare @ds TABLE (id int, value int, acc_no int, dt datetime)
INSERT INTO @ds
SELECT  1, 12, 1, '2019-01-01 07:40:38.250' UNION
SELECT  2, 14, 1, '2019-01-02 07:41:05.883' UNION
SELECT  3, 15, 1, '2019-01-13 07:41:22.377' UNION
SELECT  4, 10, 2, '2019-01-14 08:15:53.403' UNION
SELECT  5, 16, 2, '2019-01-03 13:52:47.347' UNION
SELECT  6, 19, 1, '2019-01-09 13:53:56.317' UNION
SELECT  7,  7, 3, '2019-01-17 00:00:00.000' UNION
SELECT  8, 24, 2, '2019-01-17 00:00:00.000' UNION
SELECT  9, 19, 2, '2019-01-02 00:00:00.000' UNION
SELECT 10,  7, 1, '2019-01-07 00:00:00.000' UNION
SELECT 11, 24, 1, '2019-01-05 14:12:47.080' UNION
SELECT 12, 20, 3, '2019-01-28 00:00:00.000'

SELECT id, value, acc_no, dt, value - previous AS result
FROM (
  SELECT ROW_NUMBER() OVER (PARTITION BY DS1.id
                            ORDER BY     DS2.dt DESC) AS rn
  ,DS1.*, COALESCE(DS2.value,0) AS previous
  FROM      @ds DS1
  LEFT JOIN @ds DS2
    ON      DS2.acc_no = DS1.acc_no
    AND     DS2.dt     < DS1.dt
) AS dt
WHERE rn = 1

在原始查询中,您加入了ID,在所需结果中的注释表明您要使用订购日期,而不是ID。

因此,您可以通过将“ id <t.id”更改为“ adate <t.adate”来解决原始查询

我认为您在正确的轨道上。 您需要在外部查询中使用order by并修复表别名:

SELECT ds.id, ds.value, ds.acc_no, ds.adate, 
       (t.value - COALESCE(prev.value, 0)) AS result 
FROM TB_DailyStatementt ds OUTER APPLY 
    (SELECT TOP (1) ds2.value
     FROM TB_DailyStatement ds2
     WHERE ds2.id < ds.t.id AND ds2.acc_no = ds.acc_no
     ORDER by ds2.id DESC
    ) prev
ORDER BY ds.acc_no, ds.adate

尝试这个:

    Select  *, CASE WHEN LAG(value) OVER(partition by acc_no order by adate) IS NULL THEN value
    ELSE value - LAG(value) OVER(partition by acc_no order by adate) END  result from TB_DailyStatement

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM