我想识别其值从正值转换为零或负值的ID。
所以,如果我们有一个表格如下:
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
结果应该如下,其中ID 2的值从100转换为0,ID 3的值从5转换为-10,ID 5的值从25转换为-3。我们对ID 6不感兴趣,因为它的值从负值转换为正值 - 我们只关心其值从正值到0或负值(反之亦然)的ID。我们也可以将ID从0转换为负但不是0到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
我如何取得这样的成绩?
答案 0 :(得分:1)
您可以使用分析滞后/超前函数找到每个ID的上一个和下一个值:
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
(我更改了列名,因为订单和值都是保留的)。然后,您可以将其用作子查询并过滤您想要查看的组合:
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
正如戈登所提到的,如果你只想要ID - 而不是所涉及的值 - 你只需要超前或滞后值,而不是两者。
答案 1 :(得分:1)
我认为您可以使用lead()
执行此操作:
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;
请注意,我使用了Alex的命名约定。
答案 2 :(得分:1)
这应该给你相同的结果,但是行
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)
如果这对您有用,表格将如下所示:
ID Value1 Value2
2 0 100
3 -10 5
5 -3 25
7 -10 0
8 -100 50
9 -10 0
9 0 10
答案 3 :(得分:0)
如果您使用的是Oracle 12c,这是MATCH_RECOGNIZE
的一个很好的用例。在这种情况下,它会这样做:
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
唯一的问题是,这并不包括所需输出中的以下行:
9 -10 4
在所有其他情况下,您所需的输出似乎是&#34;仅包含每个id
中有助于交叉&#34;的行。您在所需输出中包含的这一行将不符合该定义,因为这些行:
9 0 3
9 10 2
......在你自己定义的时候代表一个交叉。
如果您对所要求的输出应包含的内容有一致且更好的定义,请告知我们,我会更新我的回答。