2017-03-27 4 views
1

Ich möchte IDs identifizieren, deren Werte vom positiven Wert zum Null- oder negativen Wert übergehen.Wie identifiziert man IDs, deren Werte von positiv auf null oder negativ übergehen?

Also, wenn wir eine Tabelle wie folgt:


ID VALUES ORDER 
1 20  2 
1 10  1 
2 0  2 
2 100 1 
3 -10 2 
3 5  1 
4 0  2 
4 0  1 
5 -3  2 
5 25  1 
6 30  2 
6 -50  1 
7 -10  2 
7 0  1 
8 -100 3 
8 50  2 
8 100  1 
9 -10  4 
9 0  3 
9 10  2 
9 20  1 

Die Ergebnisse wie folgt sein sollten, in denen Werte ID 2 des 100-0 transitioned, ID 3 Werte von 5 bis -10 transitioned, ID 5s Werte wechselten von 25 zu -3. Wir sind nicht an ID 6 interessiert, da seine Werte von negativen zu positiven Werten übergegangen sind - wir interessieren uns nur für IDs, deren Werte von positiv zu 0 oder negativ (und nicht umgekehrt) gingen. Wir können auch IDs haben, dass der Übergang von 0 auf negativ, aber nicht 0 bis 0:


ID VALUES ORDER 
2 0  2 
2 100  1 
3 -10  2 
3 5  1 
5 -3  2 
5 25  1 
7 -10  2 
7 0  1 
8 -100  3 
8 50  2 
9 -10  4 
9 0  3 
9 10  2 

Wie würde ich ein solches Ergebnis zu erreichen?

+1

Woher wissen Sie, in welcher Reihenfolge der Übergang stattgefunden hat - gibt es eine weitere Spalte, in der die Reihenfolge der beiden Werte für jede ID angegeben ist?Und gibt es immer genau zwei Werte pro ID? –

+0

danke Alex. Ich habe eine Bestellliste pro ID hinzugefügt - so kam die Bestellung Nr. 1 pro ID zuerst für die ID gefolgt von Bestellung Nr. 2 und wenn es eine Bestellung Nr. 3 gab, würde dies den dritten Eintrag bedeuten. Es kann auch mehr als zwei Werte pro ID geben - dies soll nur das Konzept verdeutlichen. –

+0

OK, was passiert, wenn eine ID +3, -3, +3? Das geht in beide Richtungen über. Oder umgekehrt. Schaust du über alle Werte für eine ID irgendwie oder sequenzielle Paare? –

Antwort

1

Sie können den vorherigen und nächsten Wert für jede ID mit analytischer Verzögerung/Blei-Funktionen:

select id, value, seq, 
    lag(value) over (partition by id order by seq) as prev_val, 
    lead(value) over (partition by id order by seq) as next_val 
from your_table 
order by id, seq desc; 

     ID  VALUE  SEQ PREV_VAL NEXT_VAL 
---------- ---------- ---------- ---------- ---------- 
     1   20   2   10   
     1   10   1     20 
     2   0   2  100   
     2  100   1      0 
     3  -10   2   5   
     3   5   1     -10 
     4   0   2   0   
     4   0   1      0 
     5   -3   2   25   
     5   25   1     -3 
     6   30   2  -50   
     6  -50   1     30 
     7  -10   2   0   
     7   0   1     -10 
     8  -100   3   50   
     8   50   2  100  -100 
     8  100   1     50 
     9  -10   3   0   
     9   0   2   10  -10 
     9   20   1     10 
     9   10   1   20   0 

(ich die Spaltennamen geändert, als beide Ordnung und Werte sind reserviert). Sie können das dann als Unterabfrage verwenden und filtern Sie die Kombinationen, die Sie sehen wollen:

select id, value, seq 
from (
    select id, value, seq, 
    lag(value) over (partition by id order by seq) as prev_val, 
    lead(value) over (partition by id order by seq) as next_val 
    from your_table 
) 
where (prev_val >=0 and value <= 0 and not (prev_val = 0 and value = 0)) 
or (value >= 0 and next_val <= 0 and not (value = 0 and next_val = 0)) 
order by id, seq desc; 

     ID  VALUE  SEQ 
---------- ---------- ---------- 
     2   0   2 
     2  100   1 
     3  -10   2 
     3   5   1 
     5   -3   2 
     5   25   1 
     7  -10   2 
     7   0   1 
     8  -100   3 
     8   50   2 
     9  -10   3 
     9   0   2 
     9   10   1 

Als Gordon erwähnt, wenn Sie nur die IDs wollen - nicht die beteiligten Werte - Sie müssen nur die Führung oder Wert lag, nicht beide.

+0

danke Alex! das hat super funktioniert! –

1

Ich denke, man kann diese lead() mit nur tun:

select distinct id 
from (select t.*, 
      lead(value) over (partition by id order by seq) as next_val, 
     from t 
    ) t 
where value > 0 and next_val <= 0; 

Bitte beachte, dass ich Alex Namenskonventionen verwendet.

+0

Hängt davon ab, ob das OP nur die IDs benötigt oder auch die in der Frage gezeigten Werte benötigt. Dies erfasst auch nicht die ID 7, die von Null zu negativ geht. (Und hat ein überflüssiges Komma * 8-) –

+0

Dies könnte ein Anwendungsfall für MATCH_RECOGNIZE in 12c sein – BobC

+0

danke Gordon! Die Hilfe wird sehr geschätzt. –

1

Dies sollte man das gleiche Ergebnis, aber in Reihen

select t1.ID, t1.VALUES, t2.VALUES from TABLE t1 
join TABLE t2 on t1.VALUE < t2.VALUE and t1.ID = t2.ID and t1.ORDER > t2.ORDER 
where t1.ORDER = t2.ORDER +1 and not (t1.VALUE >0 and t2.VALUE >0) 

Tabelle wie folgt aussehen würde, wenn dies für Sie nützlich ist:

ID Value1 Value2 
2  0   100 
3  -10  5 
5  -3  25 
7  -10  0 
8  -100  50 
9  -10  0 
9  0   10 
+0

Ich denke nicht, dass es die zweite ID-Zeile (50, 100) oder die dritte ID 9 Zeile (10, 20) enthalten sollte? –

+0

OK, Korrigiert, jetzt ist es in Ordnung – Mocas

+0

danke @ user2410199. Die Hilfe wird sehr geschätzt. –

0

Wenn Sie Oracle 12c verwenden, dies ist ein Großer Anwendungsfall für MATCH_RECOGNIZE. In diesem Fall wäre es wie so geschehen:

SELECT id, value, ord FROM d 
MATCH_RECOGNIZE (partition by id 
        order by ord 
        all rows per match 
        after match skip past last row 
        pattern (posorzero neg | pos negorzero) 
        define 
        neg as neg.value < 0, 
        negorzero as negorzero.value <= 0, 
        pos as pos.value > 0, 
        posorzero as posorzero.value>= 0 
        ) 
order by id, ord desc; 

ID VALUE ORD 
-- ----- --- 
2  0  2 
2  100  1 
3  -10  2 
3  5  1 
5  -3  2 
5  25  1 
7  -10  2 
7  0  1 
8 -100  3 
8  50  2 
9  0  3 
9  10  2 

Die einzige Sache ist, ist dies nicht die folgende Zeile aus dem gewünschten Ausgang enthält:

9 -10  4 

In allen anderen Fällen der gewünschten Ausgabe scheint "enthalten nur die Zeilen von jedem id, die zum Cross-over beitragen". Diese eine Zeile, die Sie in Ihren gewünschten Ausgabe aufgenommen haben würde diese Definition nicht erfüllen, da diese Zeilen:

9 0  3 
9 10  2 

... selbst ein Cross-Over darstellen, wie Sie es definiert haben.

Wenn Sie eine konsistente und bessere Definition der gewünschten Ausgabe haben, lassen Sie es mich wissen und ich werde meine Antwort aktualisieren.

Verwandte Themen