Количество вхождений SQL в окне - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть логины пользователей по дате.Мое требование - отслеживать количество пользователей, которые вошли в систему за последние 90 дней.

Я новичок как в SQL в целом, так и в частности в Teradata, и я не могу заставить функционирование окна работать какМне нужно.

Мне нужен следующий результат, где ACTIVE - это число уникальных USER_ID, которые появляются в предыдущем 90-дневном окне ДАТА.

DATES        ACTIVE_IN_WINDOW
12/06/2018     20
13/06/2018     45                 
14/06/2018     65 
15/06/2018     73 
17/06/2018     24      
18/06/2018     87  
19/06/2018     34
20/06/2018     51

В настоящее время мой скрипт выглядит следующим образом.

Именно эту строку я не могу понять правильно

COUNT ( USER_ID) OVER (PARTITION BY USER_ID ORDER BY EVT_DT ROWS BETWEEN 90 PRECEDING AND  0 FOLLOWING)

Я подозреваю, что мне нужен другой набор функций для этой работы.

SELECT    b.DATES , a.ACTIVE_IN_WINDOW

FROM    

(
        SELECT 

        CAST(CALENDAR_DATE AS DATE) AS DATES FROM SYS_CALENDAR.CALENDAR

        WHERE DATES BETWEEN ADD_MONTHS(CURRENT_DATE, - 10)  AND CURRENT_DATE
) b

LEFT JOIN

(
        SELECT    USER_ID   , EVT_DT 

        , COUNT ( USER_ID) OVER (PARTITION BY USER_ID ORDER BY EVT_DT ROWS BETWEEN 90 PRECEDING AND  0 FOLLOWING) AS ACTIVE_IN_WINDOW

        FROM ENV0.R_ONBOARDING
) a

ON a.EVT_DT = b.DATES

ORDER BY b.DATES

СпасибоВам за любую помощь.

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Логика похожа на Gordon ', но non-equi-Join вместо Correlated Scalar Subquery обычно более эффективен в Teradata:

SELECT b.DATES , Count(DISTINCT USER_ID)
FROM
 (
   SELECT CALENDAR_DATE AS DATES 
   FROM SYS_CALENDAR.CALENDAR
   WHERE DATES BETWEEN Add_Months(Current_Date, - 10)  AND Current_Date
 ) b
LEFT JOIN
 ( -- apply DISTINCT before aggregation to reduce intermediate spool
   SELECT DISTINCT USER_ID, EVT_DT
   FROM ENV0.R_ONBOARDING
 ) AS a
ON a.EVT_DT BETWEEN Add_Months(b.DATES,-3) AND b.DATES
GROUP BY 1
ORDER BY 1

Конечно, это потребует большой катушки и большого процессора.

Редактировать:

Переключение на недели уменьшает накладные расходы, я использую даты вместо номеров недель (их легче изменить для других диапазонов):

SELECT b.Week , Count(DISTINCT USER_ID) 
FROM
 ( -- Return only Mondays instead of DISTINCT over all days 
   SELECT calendar_date AS Week
   FROM SYS_CALENDAR.CALENDAR 
   WHERE CALENDAR_DATE BETWEEN Add_Months(Current_Date, -9) AND Current_Date
     AND day_of_week = 2 -- 2 = Monday
 ) b 
LEFT JOIN 
 (
   SELECT DISTINCT USER_ID,
     -- td_monday returns the previous Monday, but we need the following monday
     -- covers the previous Tuesday up to the current Monday
            Td_Monday(EVT_DT+6) AS PERIOD_WEEK
   FROM ENV0.R_ONBOARDING
   -- You should add another condition to limit the actually covered date range, e.g.
   -- where EVT_DT BETWEEN Add_Months(b.DATES,-13) AND b.DATES
 ) AS a 
ON a.PERIOD_WEEK BETWEEN b.Week-(12*7) AND b.Week 
GROUP BY 1 
ORDER BY 1 

Объяснитьследует продублировать календарь в качестве подготовки к объединению продукта, в противном случае вам может потребоваться материализовать даты в изменчивой таблице.Лучше не использовать sys_calendar, статистика отсутствует, например, оптимизатор не знает, сколько дней в неделю / месяц / год и т. Д. Проверьте свою систему, должна быть таблица календаря, разработанная для нужд вашей компании (сстатистика по всем столбцам)

0 голосов
/ 05 декабря 2018

Если ваши данные не слишком велики, подзапрос может быть самым простым методом:

SELECT c.dte,
       (SELECT COUNT(DISTINCT o.USER_ID)
        FROM ENV0.R_ONBOARDING o
        WHERE o.EVT_DT > ADD_MONTHS(dte, -3) AND
              o.EVT_DT <= dte
       ) as three_month_count
FROM (SELECT CAST(CALENDAR_DATE AS DATE) AS dte
      FROM SYS_CALENDAR.CALENDAR
      WHERE CALENDAR_DATE BETWEEN ADD_MONTHS(CURRENT_DATE, - 10)  AND CURRENT_DATE
     ) c;

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

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