2014-02-17 2 views
8

У меня есть таблица данных, подробно описывающая последовательность действий строки в родительской таблице, где идентификатор столбца - это внешний ключ. Столбец SEQ - это порядок, в котором эти действия имели место, и ACTION - это то, что произошло.Oracle Последовательные действия

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 

Я пытаюсь представить данные таким образом, что я могу определить Приостановка и возобновление действия, которые не были очищены. В этом случае мой результат будет выглядеть следующим образом:

12345.00 7 SUSPEND 8 RESUME 
12345.00 9 SUSPEND 

Это случай, потому что;

SUSPEND действие 2 был удален под действием ОЧИСТИТЬ 3.

ПРИОСТАНОВИТЬ действие 4 удаляют путем воздействия CLEAR, 6.

Введение Действие 8 был удален под действием ОЧИСТИТЬ 9.

Столбец 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 

Я попробовал несколько подходов, но я просто не могу понять, как остановить RESUME под номером 3 включаются.

+2

действие 9 является приостановить. Я немного озадачен этим. – abhi

+0

Действие 10 «RESUME» было очищено, поэтому действие SUSPEND не было прекращено. – cbm64

ответ

3

OK.Теперь я ворую скрипку от 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. Затем я использовал фрагмент kordirko LEAD, чтобы выполнить работу с фильтром на нужном ACTION.

Смотрите скрипку here

+0

Что произойдет, если у вас есть два действия SUSPEND в строке? – smnbbrv

+0

логически и практически невозможно ... Но можно настроить данные и не обрабатывать. Если OP может подтвердить этот случай, мы можем переработать. Решение основано исключительно на том, что запросил ОП. – SriniV

5

Try:

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' 

демо: http://sqlfiddle.com/#!4/5ea45/8

+0

Действительно близко ... но последнее действие RESUME было очищено, поэтому мы не хотим его видеть. – cbm64

+0

не будет работать это решение, если оно было изменено на: WHERE action in («SUSPEND», «RESUME»)? Во всяком случае, +1 – tbone

3

Я попытался с sqlfiddle из kordirko, чтобы не строить ту же схему ... Извините за кражу.

Смотрите мою попытку здесь: 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) 

Идея такова:

  1. Возьмите только действия, которые не очищены и не «ясно» сами по себе
  2. Узнайте следующее действие который является «возобновлением», глядя только в будущее и получая минимум
  3. Отфильтровать результат, чтобы исключить «текущий ряд»

Осталось только добавить имена действий, которые достаточно просты, потому что каждое первое действие - «SUSPEND», а во-вторых, если оно не равно null, «RESUME». Это, я думаю, вы можете легко сделать самостоятельно, как пожелаете :)

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) 
+0

, но он не – smnbbrv

Смежные вопросы