Oracle получает дату последнего изменения на основе критериев - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть следующая таблица tbl_subscription.

+-----------+--------+----------+--------+
| Sub.Date  |   ID   | POSITION | STATUS |
+-----------+--------+----------+--------+
| 8/22/2018 | 254515 | BROWN    | OPEN   |
| 8/21/2018 | 254515 | ORANGE   | CLOSE  |
| 8/20/2018 | 254515 | RED      | CLOSE  |
| 8/19/2018 | 254515 | ORANGE   | CLOSE  |
| 8/18/2018 | 254515 | BLUE     | CLOSE  |
| 8/17/2018 | 254515 | BLUE     | CLOSE  |
| 8/16/2018 | 254515 | BLUE     | CLOSE  |
| 8/15/2018 | 254515 | BLUE     | CLOSE  |
| 8/14/2018 | 254515 | ORANGE   | CLOSE  |
| 8/13/2018 | 254515 | BLUE     | CLOSE  |
+-----------+--------+----------+--------+

Я действительно изо всех сил пытаюсь получить ниже. У меня есть тысячи таких записей с разными идентификаторами. Мне нужно получить все открытые записи вместе с тем, когда он был недавно изменен с синего на другую позицию См. Ниже, недавно, позиция была изменена с синего на оранжевый 8/19/2018. Итак, я хочу видеть такие данные.

+-----------+--------+----------+--------+-----------------+
| Sub.Date  |   ID   | POSITION | STATUS | Pos. Changed on |
+-----------+--------+----------+--------+-----------------+
| 8/22/2018 | 254515 | BROWN    | OPEN   | 8/19/2018       |
+-----------+--------+----------+--------+-----------------+

Я даже не понимаю, как этого добиться. Возможно ли это по крайней мере с запросом Oracle.

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

Вот один из способов:

WITH your_table AS (SELECT to_date('22/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BROWN' position, 'OPEN' status FROM dual UNION ALL
                    SELECT to_date('21/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('20/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'RED' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('19/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('18/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('17/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('16/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('15/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('14/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('13/08/2018', 'dd/mm/yyyy') sub_date, 254515 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('21/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BROWN' position, 'OPEN' status FROM dual UNION ALL
                    SELECT to_date('20/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('19/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'RED' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('18/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('17/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('16/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
                    SELECT to_date('15/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('14/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('13/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'ORANGE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('12/08/2018', 'dd/mm/yyyy') sub_date, 254516 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('29/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
                    SELECT to_date('28/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'CLOSED' status FROM dual UNION ALL
                    SELECT to_date('27/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'BLUE' position, 'OPEN' status FROM dual UNION ALL
                    SELECT to_date('26/08/2018', 'dd/mm/yyyy') sub_date, 1 ID, 'YELLOW' position, 'CLOSED' status FROM dual),
        mid_res AS (SELECT sub_date,
                           ID,
                           position,
                           status,
                           CASE WHEN LAG(position) OVER (PARTITION BY ID ORDER BY sub_date) = 'BLUE' AND position != 'BLUE' THEN sub_date END blue_to_non_blue_dt
                    FROM   your_table),
            res AS (SELECT sub_date,
                           ID,
                           position,
                           status,
                           blue_to_non_blue_dt,
                           last_value(blue_to_non_blue_dt IGNORE NULLS) OVER (PARTITION BY ID ORDER BY sub_date) latest_blue_to_non_blue_dt
                    FROM   mid_res)
SELECT sub_date,
       ID,
       position,
       status,
       latest_blue_to_non_blue_dt
FROM   res
WHERE  status = 'OPEN'
ORDER BY ID, sub_date DESC;

SUB_DATE            ID POSITION STATUS LATEST_BLUE_TO_NON_BLUE_DT
----------- ---------- -------- ------ --------------------------
29/08/2018           1 BLUE     OPEN   
27/08/2018           1 BLUE     OPEN   
22/08/2018      254515 BROWN    OPEN   19/08/2018
21/08/2018      254516 BROWN    OPEN   18/08/2018
16/08/2018      254516 BLUE     OPEN   13/08/2018

Это работает, сначала находя строки, где предыдущая строка была СИНИЙ, а текущая строка не СИНИЙ. Затем оно заполняет это значение в последующих строках перед окончательной фильтрацией, показывая только открытые строки.

Я предположил, что у вас может быть несколько строк OPEN для идентификатора, и что вы хотите, чтобы последняя дата изменения изменялась для каждой строки OPEN, поэтому я добавил дополнительные примеры данных, чтобы продемонстрировать, как это будет выглядеть (идентификаторы 1 и 254516).

0 голосов
/ 01 ноября 2018

Вы можете сделать это, просто используя оконные функции:

select t.*
from (select t.*,
             max(case when position = 'ORANGE' and prev_position = 'BLUE' then sub_date end) over (partition by id) as change_date
      from (select t.*,
                   lag(position) over (partition by ID order by sub_date) as prev_position
            from t
           ) t
      ) t
where status = 'OPEN';
0 голосов
/ 01 ноября 2018

Вы можете использовать функцию lag windows как:

select ttt.*,
(
  select max(tt.sub_date)
    from
  (  
    select t.*,
           lag(POSITION) over (partition by ID order by Sub_Date ) lg       
      from tab t 
  ) tt
  where STATUS != 'OPEN'
    and tt.POSITION = 'ORANGE'
    and tt.lg = 'BLUE'
) as changed_on
  from tab ttt
 where STATUS = 'OPEN';

Демонстрация SQL Fiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...