通过时间戳自连接减去值

时间:2017-01-12 08:38:47

标签: oracle date time

我有以下问题:
表1:

id,     timestamp,    value1,value2,value3 
1, 12.01.2017 09:00:01, 234,   345,  456  
2, 12.01.2017 09:00:05, 567,   678,  789  
3, 12.01.2017 09:00:25, 777,   888,  999  

值是绝对值。现在我需要将此数据插入到新表中,但作为增量值。 这意味着我必须找到每条记录的先前记录并减去这些值 但不幸的是我没有到达那里...... 我尝试过像这样的自我加入:

select  
    se1.timestamp,
    se1.value1,
    se1.value2,
    se1.value3
from
    table1 se1,
    table1 se2
where
    se1.id = se2.id
    and se1.timestamp < (select max(timestamp) from table1)
order by
    timestamp desc
fetch first 100 rows only;
如果有人能帮助我,那就太好了......

输出应该如下所示:

timestamp,         value1, value2, value3  
12.01.2017 09:00:05, 333,   333,   333  (record from 09:00:01 subtracted)  
12.01.2017 09:00:25, 210,   210,   210  (record from 09:00:05 subtracted) 

我希望任何人都能理解这一点;)

1 个答案:

答案 0 :(得分:2)

如果我理解得很清楚,您需要计算每个值(value1value2value3)当前行中的值与前一行中的值之间的差异,由timestamp排序。 如果是这样,您可能需要:

with test(id,     timestamp,    value1, value2, value3) as (  
  select 1, to_timestamp('12.01.2017 09:00:01', 'dd.mm.yyyy hh24:mi:ss'), 234,   345,  456 from dual union all  
  select 2, to_timestamp('12.01.2017 09:00:05', 'dd.mm.yyyy hh24:mi:ss'), 567,   678,  789 from dual union all  
  select 3, to_timestamp('12.01.2017 09:00:25', 'dd.mm.yyyy hh24:mi:ss'), 777,   888,  999 from dual
)
select timestamp,
       value1 - lag(value1, 1, 0) over ( order by timestamp) increment1,
       value2 - lag(value2, 1, 0) over ( order by timestamp) increment2,
       value3 - lag(value3, 1, 0) over ( order by timestamp) increment3
from test

这使用LAG来评估前一行并与当前行中的值产生差异,从而给出:

TIMESTAMP                      INCREMENT1  INCREMENT2  INCREMENT3
12/01/2017 09:00:01,000000000  234         345         456
12/01/2017 09:00:05,000000000  333         333         333
12/01/2017 09:00:25,000000000  210         210         210

请注意,timestamp是Oracle类型,因此最好不要将其用作列的名称。

另外,请注意Boneist的评论:在我的回答的第一个版本中,我使用类似NVL(LAG(..), 0)的内容来处理LAG(..)null(第一行)的情况。 Boneist的评论让我注意到LAG已经处理了一个默认值,以防所需的前一行不存在,从而允许我避开NVL