2014-10-20 1 views
0

Я хочу определить пользователей, которые посетили раздел a, а затем посетили b. Учитывая следующую структуру данных. Таблица содержит 300 000 строк и обновлений ежедневно прибл. 8 000 строк:Как определить последующие действия пользователя на основе предыдущих посещений

**USERID** **VISITID**  **SECTION** Desired Solution--> **Conversion** 
    1    1    a          0 
    1    2    a          0 
    2    1    b          0 
    2    1    b          0 
    2    1    b          0 
    1    3    b          1 

В идеале я хочу новый столбец, который обозначает посещение раздела b. Например, в третьем визите Пользователь 1 впервые посетил раздел b. Я пытался сделать это, используя инструкцию CASE WHEN, но после многих неудачных попыток я не уверен, что это возможно даже с CASE WHEN и чувствую, что я должен придерживаться другого подхода, я просто не уверен, каким должен быть этот подход. У меня также есть столбец даты в моем распоряжении.

Любые предложения по новому способу подхода к проблеме будут оценены по достоинству. Благодаря!

+0

Или я предположил помощь по выполнению желаемого решения с помощью CASE КОГДА было бы полезно. – camacnei

+0

В моем вопросе я отметил, что у меня также есть столбец даты в моем распоряжении. (содержит информацию о времени до второй) – camacnei

ответ

1

При работе с Redshift следует избегать коррелированных подзапросов. Имейте в виду, что для Redshift нет индексов, поэтому вам нужно будет выполнить повторное сканирование и восстановить данные столбца вместе для каждого значения в родительском объекте, что приведет к операции O (n^2) (в данном конкретном случае, начиная с 300 тыс. значения отсканированы до 90 млрд.).

Лучший подход, когда вы хотите охватить ряд строк, - использовать аналитическую функцию. Есть несколько вариантов, в зависимости от того, как данные структурированы, но в простейшем случае, вы могли бы использовать что-то вроде

select case 
     when section != lag(section) over (partition by userid order by visitid) 
     then 1 
     else 0 
     end 
from ... 

Это предполагает, что ваши данные для идентификатора пользователя 2 приращений visitid, как показано ниже. Если нет, вы также можете заказать свою временную колонку

**USERID** **VISITID**  **SECTION** Desired Solution--> **Conversion** 
    1    1    a          0 
    1    2    a          0 
    2    1    b          0 
    2   *2*    b          0 
    2   *3*    b          0 
    1    3    b          1 
+0

Это намного быстрее, и я могу запустить его на большом наборе данных без сбоев в моем рабочем столе SQL. Благодаря! – camacnei

+0

Он делает это, но, похоже, удвоить метрику, которую я искал. – camacnei

+0

@camacnei Это потому, что он не делает то, что вы хотите. Когда вы говорите: «Я хочу идентифицировать пользователей, которые посетили раздел a, а затем впоследствии посетили b». Я сомневаюсь, что вы ИСКЛЮЧИТЕЛЬНО хотите, чтобы пользователи, которые сразу же отправились в a, а затем b. Например, если пользователь переходит к a, а затем в c, а затем в b, вышеуказанный запрос не нашел бы этого.Это только поиск строк, где пользователь сразу же отправился в a, а затем в b, а не на пользователей, которые пошли на b, и ANYTIME PREVIOUSLY отправились в. Он находит только пользователей, которые ТОЛЬКО ПРЕДЫДУЩИЕ пошли на. –

1
select t.*, case when v.ts is null then 0 else 1 end as conversion 
    from tbl t 
    left join (select * 
       from tbl x 
       where section = 'b' 
       and exists (select 1 
         from tbl y 
         where y.userid = x.userid 
         and y.section = 'a' 
         and y.ts < x.ts)) v 
    on t.userid = v.userid 
    and t.visitid = v.visitid 
    and t.section = v.section 

Фидл: http://sqlfiddle.com/#!15/5b954/5/0

Я добавил данные метки времени выборки, как и поле, необходимо, чтобы определить, идет ли до того или после б б.

Чтобы включить аналитические функции, которые вы могли бы использовать:

(Я также сделал так, что только первое вхождение B (после А) получит помечено 1)

select t.*, 
     case 
     when v.first_b_after_a is not null 
     then 1 
     else 0 
     end as conversion 
    from tbl t 
    left join (select userid, min(ts) as first_b_after_a 
       from (select t.*, 
          sum(case when t.section = 'a' then 1 end) 
            over(partition by userid 
             order by ts) as a_sum 
         from tbl t) x 
       where section = 'b' 
       and a_sum is not null 
       group by userid) v 
    on t.userid = v.userid 
    and t.ts = v.first_b_after_a 

Fiddle:http://sqlfiddle.com/#!1/fa88f/2/0

+0

Я никогда не видел CASE КОГДА используется как этот bu, то снова я довольно новичок в SQL! Никогда бы не подумал объединить соединение и случай, когда так. Спасибо! Вы! Попробуйте это сейчас ... – camacnei