2017-01-12 2 views
2

Ich habe folgendes Problem:
Tabelle 1:subtrahieren Werte durch Zeitstempel Selbst Auswahl beitreten

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 

die Werte sind absolut Werte. Jetzt muss ich diese Daten in eine neue Tabelle einfügen, aber als inkrementelle Werte. das bedeutet, ich muss den vorherigen Datensatz für jeden Datensatz finden und die Werte subtrahieren.
aber leider im nicht dorthin zu gelangen ... ich ein selbst wie diese verbinden versucht:

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; 

, es wäre toll, wenn jemand mir mit diesem ...

sollte

Der Ausgang etwas aussehen könnte helfen wie folgt aus:

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) 

ich jemand hoffen, dass dies verstehen kann;)

+0

OOps. Ich habe vergessen, den Code zu formatieren: – Monument

+1

Ich bekomme Ihre Frage nicht, können Sie bitte Beispiel der gewünschten Ausgabe angeben? –

+0

Sie können Ihre Frage einfach bearbeiten, um Code und Daten zu formatieren (Hinweis: Strg + k) – Aleksej

Antwort

2

Wenn ich gut verstehen Sie, müssen für jeden Wert (, value2 und value3) die Differenz zwischen dem Wert in der aktuellen Zeile und dem Wert in der vorherigen Zeile, geordnet nach timestamp, berechnen. Wenn ja, können Sie benötigen:

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 

Diese LAG verwenden die vorhergehende Reihe und macht den Unterschied mit dem Wert in der aktuellen Zeile zu bewerten, so geben:

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 

Beachten Sie, dass timestamp eine ist Oracle-Typ, es wäre also besser, ihn nicht als Namen einer Spalte zu verwenden.

Beachten Sie auch, die Kommentare von Boneist: in der ersten Version meiner Antwort, die ich so etwas wie NVL(LAG(..), 0) verwendet, um den Fall zu behandeln, in denen LAG(..)null (die erste Zeile) ist. Der Kommentar von Boneist ließ mich bemerken, dass LAG bereits einen Standardwert behandelt, falls die benötigte vorherige Zeile nicht existiert, so dass ich die NVL vermeiden kann.

+1

Sie brauchen die NVL hier nicht; Sie können die zusätzlichen Parameter von ['LAG()'] (https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions082.htm#SQLRF00652) verwenden, um Nullen, z. 'LAG (Wert1, 1, 0) OVER ...' – Boneist

+1

@Boneist immer etwas zu lernen .. danke – Aleksej

+0

@Boneist teilweise Bearbeitung, sorry – Aleksej

Verwandte Themen