2013-04-30 2 views
2

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

У меня есть monhtly снимок со следующим данные:

customer | month  | last_action | last_action_date 
1   01-01-2012 subscription 01-01-2012 
1   02-01-2012 subscription 01-01-2012 
1   03-01-2012 subscription 01-01-2012 
1   04-01-2012 downgrade  04-01-2012 
1   05-01-2012 downgrade  04-01-2012 
1   06-01-2012 downgrade  04-01-2012 
1   07-01-2012 unsubscription 07-01-2012 

Как вы можете видеть, действие известно лишь в месяц, как это делается, в месяц 01.01.2012 мы не знаем, пока клиент понижен в 04.01.2012 так мы не можем проанализировать его поведение использования относительно его месяца понижения. То же самое для отмены подписки.

Необходимый набор данных заключается в следующем:

customer | month  | downgrade_date | unsubscription_date 
1   01-01-2012 04-01-2012   07-01-2012 
1   02-01-2012 04-01-2012   07-01-2012 
1   03-01-2012 04-01-2012   07-01-2012 
1   04-01-2012 12-31-9999   07-01-2012 
1   05-01-2012 12-31-9999   07-01-2012 
1   06-01-2012 12-31-9999   07-01-2012 
1   07-01-2012 12-31-9999   07-01-2012 

Я мог бы легко отписку дату с last_value аналитической функции, но не нашел способ получить дату понижения.

Вот мой SQL-запрос:

SELECT month_id, 
     customer_id, 
     CASE 
     WHEN LAST_VALUE(last_action) OVER (PARTITION BY customer_id ORDER BY month_id RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) = 'unsubscription' THEN LAST_VALUE(last_action_date) OVER (PARTITION BY customer_id ORDER BY month_id RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)  
     ELSE TO_DATE('99991231', 'yyyymmdd') 
     END unsubscription_date 
FROM my_table 
; 

Любой способ получить «следующий» дата действий, как в «downgrade_date».

Я использую Oracle.

+0

Заканчивать функция 'lead()'. –

ответ

1

В оракула 11, вы можете сделать это с помощью lead() и ignore nulls вариант:

select customer, MONTH, 
     lead(case when last_action = 'downgrade' then last_action_date end ignore nulls) over 
       (partition by customer order by month desc) as downgrade_date, 
     lead(case when last_action = 'unsubscription' then last_action_date end ignore nulls) over 
       (partition by customer order by month desc) as downgrade_date, 
from my_table t 

Если у вас нет ignore nulls, вы можете сделать что-то подобное с min():

select customer, MONTH, 
     min(case when last_action = 'downgrade' then last_action_date end) over 
       (partition by customer order by month range between current and unbounded following 
       ) as downgrade_date, 
     min(case when last_action = 'unsubscription' then last_action_date end) over 
       (partition by customer order by month range between current and unbounded following 
       ) as unsubscription_date 
from my_table t 
+0

Спасибо Гордону, запрос min() не работает, и проблема со свинцом заключается в том, что я получаю downgrade_date только в одной строке, предшествующей предыдущему и следующему. – user2018454

+0

@ пользователь2018454. , , Я предполагаю, что запрос 'lead()' работает из-за версий Oracle. 'Min()' упорядочивался на 'month desc', а затем делал все до конца - это означало, что он смотрел на более ранние месяцы. Удалите 'desc' и посмотрите, работает ли это. –

+0

Это нормально, когда вы заказываете по месяцам, спасибо большое – user2018454

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