【问题标题】:Subtract previous row value to current row and order by date将前一行值减去当前行并按日期排序
【发布时间】:2019-06-13 23:41:24
【问题描述】:

我的表中数据如下

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

【问题讨论】:

  • 看看LEAD 和/或LAG
  • 我试过了,但是不行
  • 我没有听说过领先或滞后,但你可以直接加入同一个表,id 为 -1,所以 tbl1.id = isnull(tbl2.id, 0) - 2?
  • 没关系,刚刚注意到你标记了 2008。你知道那基本上完全不支持了吧?
  • 我也试过了,但我按 adate 和 acc_no 执行了订单,因为这不能正常工作

标签: c# sql sql-server sql-server-2008


【解决方案1】:

如果你想通过 acc_no asc 简单的排序得到这个结果,你可以得到你期望的简单结果,

例如

按 acc_no acs 从表顺序中选择 *

【讨论】:

  • 但我也必须从当前行中减去前一行
【解决方案2】:

SQL Server 2008,你不能使用LEAD &amp; 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 为您提供所需的上一个和下一个值。现在您可以应用 switch case 来格式化字符串。

查看Demo

【讨论】:

  • 未按预期工作,未按日期和 acc_no 排序
  • 什么不工作,你没有得到预期的结果吗?
  • 我已经更新了演示链接,你可以查看输出。
  • 在想要的当前行值中替换空值
【解决方案3】:
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,所需结果中的 cmets 表明您希望使用日期进行订购,而不是 id。

因此,您可以通过将“id

【讨论】:

    【解决方案4】:

    我认为你在正确的轨道上。您需要在外部查询中使用 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
    

    【讨论】:

      【解决方案5】:

      试试这个:

          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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-21
        • 2021-01-04
        • 2015-08-10
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2012-04-29
        相关资源
        最近更新 更多