2016-11-18 3 views
0

У меня есть таблица журналов соединений для клиентов в нашей базе данных, и я ежедневно рассчитываю количество соединений, которые каждый клиент совершил за предыдущие семь дней. Таблица источника я использую имеет схемуПодсчитайте количество сеансов за последние X дней

uuid, sessionuid, connection_timestamp 

То, что я хочу, как выход

uuid, _date, total_connections_over_trailing_seven_days, 

так, что я могу видеть, для данного учетной записи клиента и определенной даты, как много раз, что человек связал в последние семь (или что-то еще) предыдущие дни.

Запрос я написал для достижения этой цели является

SELECT 
    uuid, 
    connection_timestamp::date as _date, 
    COUNT(sessionuid) OVER (ORDER BY timestamp_session ROWS 6 PRECEDING) as trailing_seven_day_session_count 
FROM connection_history_table 

Но когда я выполнить этот запрос, я получаю отдельную строку для каждого пользователя, и каждый connection_timestamp в исходной таблице вместо одной записи для каждого уникального connection_timestamp :: даты. Кроме того, значение в trailing_seven_day_session_count увеличивается с 1 до максимального значения 7 (если в данный день есть как минимум 7 сеансов), но после этого не увеличивается. Поэтому кажется, что я подсчитываю количество сеансов в определенный день, но только за первые 7 сеансов.

uuid  _date    trailing_seven_day_session_count 
16398 2015-02-18 00:00:00 1 
16398 2015-02-18 00:00:00 2 
16398 2015-02-18 00:00:00 3 
16398 2015-02-18 00:00:00 4 
16398 2015-02-18 00:00:00 5 
16398 2015-02-18 00:00:00 6 
16398 2015-02-18 00:00:00 7 
16398 2015-02-18 00:00:00 8 
16398 2015-02-18 00:00:00 8 
16398 2015-02-25 00:00:00 1 
16398 2015-02-25 00:00:00 2 
16398 2015-02-25 00:00:00 3 
16398 2015-02-25 00:00:00 4 
16398 2015-02-25 00:00:00 5 
16398 2015-02-25 00:00:00 6 
16398 2015-02-25 00:00:00 7 
16398 2015-02-25 00:00:00 8 
16398 2015-02-25 00:00:00 8 

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

Спасибо, Брэда

ответ

1

Может быть, вам нужно подсчитать сессии на каждый день, а затем сделать сумму предыдущих дней. Что-то вроде этого:

select 
    uuid, 
    day, 
    sum(sessions) over (partition by uuid order by day rows 6 preceding) as trailing_seven_day_session_count 
from (select uuid, connection_timestamp::date as day, count(*) sessions 
    from connection_history_table 
    group by 1,2) 
order by 1,2 

Что касается комментариев Брэда о разреженных данных, вот возможный подход. Он генерирует нулевые записи для заполнения дней, поэтому оглядываясь назад, количество записей будет коррелировать с днями. Не побежали, но это должно быть довольно близко. Поскольку он генерирует дни, ему нужен общий временной диапазон, который необходимо настроить. Я не уверен, что у меня есть дневные диапазоны и исправление вправо ... он пытается получить данные за день на 37 дней для создания записей в течение 30 дней.

with days as (
    -- hack to generate days in redshift like a generate_series function 
    select (dateadd(day, -row_number() over (order by true), sysdate::date)) as day 
      from stv_blocklist limit 37 
), 
day_counts as (
    select uuid, connection_timestamp::date as day, count(*) sessions 
    from connection_history_table 
    where connection_timestamp >= sysdate-37 
    group by 1,2 
), 
zero_days as (
    select s.uuid, d.day, 0 as sessions 
    from (
     select distinct uuid from connection_history_table 
     where connection_timestamp >= sysdate-37 
    ) s 
    cross join days d 
) 
select 
    uuid, 
    day, 
    sum(sessions) over (partition by uuid order by day rows 6 preceding) as trailing_seven_day_session_count 
from (
    select uuid, day, sessions from day_counts 
    union all 
    select uuid, day, sessions from zero_days z 
     left join day_counts c on z.uuid=c.uuid and z.day=c.day 
     where c.uuid is null 
) 
having day >= sysdate-30 
order by 1,2 
+0

Да, я пробовал что-то подобное, но он не получает того, чего я хочу, потому что он рассчитывает на предыдущие шесть строк, и я не обязательно должен иметь строку для повседневности. У меня есть только ежедневная игра, которую пользователь играл. Поэтому я должен придумать совершенно другое решение. Спасибо за вашу помощь. Я собираюсь поднять ваше решение и принять его, потому что он решает исходную проблему, которую я опубликовал, просто не проблема, которую я действительно имею. : –

+0

Должно ли это быть однократным выстрелом или можно запустить запрос итеративно ... сказать один раз в день? Если вы можете сделать это ежедневно, вы можете добавить предложение where во внутренний select, который выбирает только записи, где connection_timestamp> = sysdate-7, чтобы получить то, что вы хотите. – systemjack

+0

Добавлен janky-запрос для обработки нулевых дней. – systemjack

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