【问题标题】:subtract values selecting by timestamp self join减去通过时间戳自连接选择的值
【发布时间】:2017-01-12 08:38:47
【问题描述】:

我有以下问题:
表一:

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) 

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

【问题讨论】:

  • OOps。我忘了格式化代码:
  • 我不明白你的问题,你能提供所需输出的例子吗?
  • 您可以轻松编辑您的问题以格式化代码和数据(提示:ctrl+k)
  • @Wernfied Domscheid:我试图在帖子中更好地解释一下。我希望这有助于理解
  • @Aleksej:谢谢。我现在更新了...

标签: oracle date time


【解决方案1】:

如果我理解得很好,您需要为每个值(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 的 cmets:在我的答案的第一个版本中,我使用了类似 NVL(LAG(..), 0) 的东西来处理 LAG(..)null(第一行)的情况。 Boneist 的评论让我注意到LAG 已经处理了一个默认值,以防所需的前一行不存在,因此我可以避免NVL

【讨论】:

  • 这里不需要 NVL;您可以使用LAG() 的附加参数来处理空值,例如LAG(value1, 1, 0) OVER ...
  • @aleksej 非常感谢。这将帮助我......直到现在我都错过了 LAG() 函数...... ;) 再次感谢!
  • @Monument - 不客气。 Here 你会发现更多关于如何处理你的问题的答案
猜你喜欢
  • 2011-04-02
  • 2013-02-09
  • 2014-04-25
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多