我有一个数据表详细说明父表上行的操作顺序,其中列ID是该外键。列SEQ是这些动作发生的顺序,ACTION是发生的动作。
ID SEQ ACTION
12345.00 2 SUSPEND
12345.00 3 CLEAR
12345.00 4 SUSPEND
12345.00 6 CLEAR
12345.00 7 SUSPEND
12345.00 8 RESUME
12345.00 9 SUSPEND
12345.00 10 RESUME
12345.00 11 CLEAR
我试图以这样一种方式呈现数据,即我可以识别未清除的SUSPEND和RESUME操作。在这种情况下,我的结果将如下所示;
12345.00 7 SUSPEND 8 RESUME
12345.00 9 SUSPEND
这是因为;
CLEAR行动3删除了SUSPEND行动2.
CLEAR行动6删除了SUSPEND行动4。
清除行动9删除了RESUME动作8。
ACTION列可以在序列中包含其他操作,因此为了清楚起见,我删除了这些操作。
如果CLEAR将继续操作,则清除操作。
很抱歉,如果这令人困惑。我无法改变架构!
我试图简化问题;
ID SEQ ACTION
12345.00 2 SUSPEND
12345.00 3 RESUME
12345.00 4 CLEAR
12345.00 5 RESUME
12345.00 6 SUSPEND
结果应如下所示;
12345.00 2 SUSPEND 5 RESUME
12345.00 6 SUSPEND
我尝试了几种方法,但我无法想象如何停止包含3号的RESUME。
答案 0 :(得分:5)
尝试:
SELECT *
FROM (
SELECT t.*,
lead( SEQ ) over ( partition by id order by seq ) next_seq,
lead( action ) over ( partition by id order by seq ) next_action
FROM table1 T
)
WHERE action = 'SUSPEND'
AND next_action <> 'CLEAR'
答案 1 :(得分:3)
我尝试从 kordirko 的sqlfiddle,以避免构建相同的架构...抱歉偷了。
在此处查看我的尝试:http://sqlfiddle.com/#!4/5ea45/22
select *
from (select id,
seq,
min(case when action != 'SUSPEND' then seq end) over (partition by id order by seq rows between current row and unbounded following) nxt
from (select t.*,
lead(action) over (partition by id order by seq) nxt
from table1 t)
where nxt != 'CLEAR'
and action != 'CLEAR')
where (seq != nxt or nxt is null)
这个想法是:
唯一要做的就是添加非常简单的动作名称,因为每个第一个动作都是“SUSPEND”,第二个动作是非空的“RESUME”。我猜你可以随心所欲地做到这一点:)
答案 2 :(得分:3)
行。现在我从kordirko窃取小提琴,从simon偷取概念,然后按照我的方式做饭。
CREATE TABLE TABLE1
(
"ID" INT,
"SEQ" INT,
"ACTION" VARCHAR2 ( 7 )
);
INSERT ALL
INTO TABLE1 ( "ID", "SEQ", "ACTION" )
VALUES ( 12345.00, 2, 'SUSPEND' )
INTO TABLE1 ( "ID", "SEQ", "ACTION" )
VALUES ( 12345.00, 3, 'RESUME' )
INTO TABLE1 ( "ID", "SEQ", "ACTION" )
VALUES ( 12345.00, 4, 'CLEAR' )
INTO TABLE1 ( "ID", "SEQ", "ACTION" )
VALUES ( 12345.00, 5, 'RESUME' )
INTO TABLE1 ( "ID", "SEQ", "ACTION" )
VALUES ( 12345.00, 6, 'SUSPEND' )
SELECT * FROM DUAL;
所以我从你的问题中理解的是,它最初没有正确解释。但第二个预期的结果就是诀窍。 (我可能还是错了)
WITH AFTER_CHECK
AS (SELECT T.ID,
T.SEQ,
T.ACTION,
CASE
WHEN ACTION = 'CLEAR'
THEN
1
WHEN LEAD ( ACTION ) OVER (PARTITION BY ID ORDER BY SEQ) =
'CLEAR'
THEN
1
ELSE
0
END
AS IGNORE_CURRENT
FROM TABLE1 T)
SELECT *
FROM (SELECT T.ID,
T.SEQ,
T.ACTION,
LEAD ( SEQ ) OVER (PARTITION BY ID ORDER BY SEQ) NEXT_SEQ,
LEAD ( ACTION ) OVER (PARTITION BY ID ORDER BY SEQ)
NEXT_ACTION
FROM AFTER_CHECK T
WHERE IGNORE_CURRENT = 0)
WHERE ACTION = 'SUSPEND';
<强>输出:强>
12345 2 SUSPEND 5 RESUME
12345 6 SUSPEND
我所做的是分配一个标志来检查设置为忽略的连续动作,如果它们有一个名为CLEAR
的ACTION或一个名为CLEAR
的NEXT ACTION。然后我使用kordirko的LEAD
函数片段来完成所需的ACTION过滤器。
查看小提琴here
答案 3 :(得分:2)
kordirkos解决方案的这个修改版本应该有效:
SELECT *
FROM (
SELECT t.*,
lead( SEQ ) over ( partition by id order by seq ) next_seq,
lead( action ) over ( partition by id order by seq ) next_action
FROM table1 T
)
WHERE action in ('SUSPEND', 'RESUME')
AND (next_action <> 'CLEAR' or next_action is null)