Oracle顺序操作

cbm*_*m64 8 oracle plsql

我有一个数据表详细说明父表的行的动作序列,其中列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
Run Code Online (Sandbox Code Playgroud)

我试图以这样的方式呈现数据,以便我可以识别未清除的SUSPEND和RESUME操作.在这种情况下,我的结果将如下所示;

12345.00    7   SUSPEND    8    RESUME
12345.00    9   SUSPEND
Run Code Online (Sandbox Code Playgroud)

情况就是这样;

CLEAR行动3删除了SUSPEND行动2.

CLEAR行动6删除了SUSPEND行动4.

CLEAR动作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
Run Code Online (Sandbox Code Playgroud)

结果应该是这样的;

12345.00    2   SUSPEND   5 RESUME
12345.00    6   SUSPEND
Run Code Online (Sandbox Code Playgroud)

我尝试了几种方法,但我无法想象如何停止包含3号的RESUME.

kro*_*lko 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'
Run Code Online (Sandbox Code Playgroud)

演示:http://sqlfiddle.com/#!4/5ea45/8


Sri*_*niV 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;
Run Code Online (Sandbox Code Playgroud)

所以我从你的问题中了解到的是,它最初没有被正确解释。但第二个预期结果就达到了目的。(我可能还是错了)

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';
Run Code Online (Sandbox Code Playgroud)

输出:

12345   2   SUSPEND 5   RESUME
12345   6   SUSPEND     
Run Code Online (Sandbox Code Playgroud)

我所做的是分配一个标志来检查设置为忽略的连续操作,如果它们有一个名为 ACTIONCLEAR或一个名为 NEXT ACTION 的操作CLEAR。然后我使用 kordirko 的函数片段LEAD通过所需操作的过滤器来完成这项工作。

在这里查看小提琴