Логика похожа на 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
, статистика отсутствует, например, оптимизатор не знает, сколько дней в неделю / месяц / год и т. Д. Проверьте свою систему, должна быть таблица календаря, разработанная для нужд вашей компании (сстатистика по всем столбцам)