Превращение записей по диапазону дат в записи по дням / месяцам с использованием SQL Server или Vertica - PullRequest
0 голосов
/ 15 ноября 2018

Я могу использовать либо SQL Server, либо Vertica в качестве базы данных, а Tableau - в качестве инструмента отчетности. Было бы полезно найти решение в любой из этих сред.

РЕСУРСЫ ДАННЫХ: У меня есть таблица (userActivity) с 100 записями и структурой: User, StartDate, EndDate

ПОТРЕБНОСТЬ: Я заинтересован в подготовке отчетов по дням и месяцам, которые показывают «общее количество активных дней». Это означает, что если у User1 есть диапазон от «20180101» до «20180331», они будут вносить один день для каждого дня в январе, феврале и марте ИЛИ 31, 28 и 31 день, если сгруппированы по месяцам.

ЗАДАЧА: В конечном итоге я буду объединять общее количество активных дней всех пользователей в качестве выходных данных, чтобы получить единую сумму за каждый день / месяц.

Этот отчет будет продолжаться до бесконечности, поэтому я бы предпочел решения, которые не жестко кодируют утверждения CASE / IF-THEN по дням / месяцам.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 16 ноября 2018

Хотя рекурсивные CTE являются хорошим кандидатом для этого сценария, он может быть обработан только с помощью таблицы. Предполагая, что у вас есть эти данные, вот шаги, необходимые для создания представления.

enter image description here

  1. Создайте справочный лист, в котором ожидаются все дни. Даже если вам нужно покрыть 25 лет с 01.01.08 по 01.01.2043, это все равно меньше 10 тысяч строк.

enter image description here

Вам нужны два столбца с точно такой же датой, поскольку в Таблице не разрешено несколько условий объединения для одного столбца.

  1. Создание внутреннего соединения между справочным календарем и данными с использованием следующих критериев. enter image description here

  2. Построить представление

    enter image description here

0 голосов
/ 16 ноября 2018

Используйте Vertica - в нем есть предложение TIMESERIES - рекурсия не требуется.

Я бы попробовал следующее - и проверил промежуточные результаты выражений Common Table, чтобы увидеть, как это работает ..

WITH 
-- two test rows ....
input(uid,start_dt,end_dt) AS (
            SELECT 1,DATE '2018-01-01', DATE '2018-03-31'
  UNION ALL SELECT 2,DATE '2018-02-01', DATE '2018-04-01'
)
,
-- set the stage for Vertica's TIMESERIES clause
-- note: TIMESERIES relies on timestamps ...
limits(uid,lim_dt,qty) AS (
  SELECT
    uid
  , start_dt::TIMESTAMP
  , 1
  FROM input
  UNION ALL
  SELECT
    uid
  , end_dt::TIMESTAMP
  , 1
  FROM input
)
,
-- apply the Vertica TIMESERIES clause
counters AS (
  SELECT
    uid
  , act_dt
  , TS_FIRST_VALUE(qty) AS qty
  FROM limits
  TIMESERIES act_dt AS '1 DAY' OVER(PARTITION BY uid ORDER BY lim_dt)
)
SELECT
  uid
, MONTH(act_dt) AS activity_month
, SUM(qty)
FROM counters
GROUP BY 1,2;
-- out  uid | activity_month | sum 
-- out -----+----------------+-----
-- out    1 |              1 |  31
-- out    1 |              2 |  28
-- out    1 |              3 |  31
-- out    2 |              2 |  28
-- out    2 |              3 |  31
-- out    2 |              4 |   1
-- out (6 rows)
-- out 
-- out time: first fetch (6 rows): 120.515 ms. all rows formatted: 120.627 ms
0 голосов
/ 16 ноября 2018

Решение:

WITH base AS (
  SELECT
     User       AS u
    ,StartDate  AS s
    ,EndDate    AS e
    ,DATEDIFF(
      dd,
      StartDate,
      EndDate
      )+1       AS d
  FROM  userActivity
  ),
recurse AS (
  SELECT    u, s, e, d, x=(d-1)
    FROM    base
    UNION ALL
    SELECT  u, s, e, d, x-1 AS x
    FROM    recurse
    WHERE   x>0
  )
SELECT      u, DATEADD(dd, x, s) AS recordperday
FROM        recurse
ORDER BY    u, recordperday
--Extends SQL Server's recursion limit
OPTION (MAXRECURSION 500)
...