Как отфильтровать данные истории на основе самой последней записи?

Table: HISTORY
CUSTOMER    MONTH    PLAN
1           1        A
1           2        A
1           2        B
1           3        B

В этом примере клиент 1 был план A и изменился на B на месяц 2, Мне нужно убрать изменение с месяца 2 и сохраняйте только тот план, на который клиент перейдет, как в:

CUSTOMER    MONTH    PLAN
1           1        A
1           2        B
1           3        B

Я пытался использовать sys_connect_by_path:

select month, CUSTOMER, level, 
sys_connect_by_path(PLAN, '/') as path
from a
start with month = 1
connect by prior MONTH = MONTH - 1

Но это не похоже на правду. Какой эффективный способ сделать это в Oracle 12c?

2 ответа

Решение

Я не уверен, что вы поняли, что говорится в комментариях - сомнительны строки 2 и 3, потому что нет способа узнать, какой из них произошел первым.

В любом случае, как вы сказали, что в этой таблице нет ничего, что помогло бы нам решить, как насчет чего-то подобного? Сравните текущий план со следующим планом (отсортированным по месяцам) и выберите строки, в которых нет изменений в плане.

SQL> with test (customer, month, plan) as
  2    (select 1, 1, 'A' from dual union all
  3     select 1, 2, 'A' from dual union all
  4     select 1, 2, 'B' from dual union all
  5     select 1, 3, 'B' from dual
  6    ),
  7  inter as
  8    (select customer, month, plan,
  9       nvl(lead(plan) over (partition by customer order by month), plan) lead_plan
 10     from test
 11    )
 12  select customer, month, plan
 13  from inter
 14  where plan = lead_plan
 15  order by month;

  CUSTOMER      MONTH PLAN
---------- ---------- -----
         1          1 A
         1          2 B
         1          3 B

SQL>

Вы могли бы использовать аналитические lead() позвоните, чтобы посмотреть в следующем месяце, и решите, использовать ли план на текущий или следующий месяц:

-- CTE for your sample data
with history (customer, month, plan) as (
            select 1, 1, 'A' from dual
  union all select 1, 2, 'A' from dual
  union all select 1, 2, 'B' from dual
  union all select 1, 3, 'B' from dual
)
-- actual query
select distinct customer, month,
  case
    when lead(plan) over (partition by customer order by month) != plan
    then lead(plan) over (partition by customer order by month)
    else plan
  end as plan
from history;

  CUSTOMER      MONTH P
---------- ---------- -
         1          1 A
         1          2 B
         1          3 B

Вы могли бы переместить lead() Вычисление во встроенное представление, чтобы уменьшить повторение, если вы предпочитаете.

Это, вероятно, сломается интересными способами, если клиент меняет план на последовательные месяцы, или, возможно, если они могут меняться более одного раза в месяц.

Другие вопросы по тегам