通过 Day/Month 使用 SQL 服务器或 Vertica 将按日期范围的记录转换为记录
Turning Records by Date Range into Records by Day/Month Using SQL Server or Vertica
我可以使用 SQL Server 或 Vertica 作为数据库,使用 Tableau 作为报告工具。任何这些介质中的解决方案都会有所帮助。
数据资源:
我有一个包含 100 条记录的 table (userActivity),其结构为:User、StartDate、EndDate
需要:
我有兴趣按天和月准备显示 "total active days" 的报告,这意味着如果 User1 的范围是“20180101”到“20180331”,他们将在 1 月、2 月和 3 月或 31 日的每一天贡献一天,如果按月汇总,则为 28 天和 31 天。
目标:
我最终将汇总所有用户的总活跃天数作为输出,以实现每个 day/month.
的单一总数
这份报告将永久有效,所以我更喜欢不通过 day/month.
对 CASE/IF-THEN 语句进行硬编码的解决方案
谢谢!
解决方案:
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)
虽然递归 CTE 很适合这种情况,但它可以单独使用 tableau 来处理。假设您有这些数据,下面是生成视图所需的步骤。
- 创建一个引用 sheet,其中包含预期的所有天数。即使您需要涵盖从 01/01/2018 到 01/01/2043 的 25 年,那仍然少于 10k 行。
您需要两个日期完全相同的列,因为 Tableau 不允许在同一列上使用多个连接条件。
使用以下条件在参考日历和数据之间创建内部联接。
构建视图
使用 Vertica - 它有 TIMESERIES 子句 - 不需要递归。
我会尝试下面的方法 - 并检查通用 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
我可以使用 SQL Server 或 Vertica 作为数据库,使用 Tableau 作为报告工具。任何这些介质中的解决方案都会有所帮助。
数据资源: 我有一个包含 100 条记录的 table (userActivity),其结构为:User、StartDate、EndDate
需要: 我有兴趣按天和月准备显示 "total active days" 的报告,这意味着如果 User1 的范围是“20180101”到“20180331”,他们将在 1 月、2 月和 3 月或 31 日的每一天贡献一天,如果按月汇总,则为 28 天和 31 天。
目标: 我最终将汇总所有用户的总活跃天数作为输出,以实现每个 day/month.
的单一总数这份报告将永久有效,所以我更喜欢不通过 day/month.
对 CASE/IF-THEN 语句进行硬编码的解决方案谢谢!
解决方案:
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)
虽然递归 CTE 很适合这种情况,但它可以单独使用 tableau 来处理。假设您有这些数据,下面是生成视图所需的步骤。
- 创建一个引用 sheet,其中包含预期的所有天数。即使您需要涵盖从 01/01/2018 到 01/01/2043 的 25 年,那仍然少于 10k 行。
您需要两个日期完全相同的列,因为 Tableau 不允许在同一列上使用多个连接条件。
使用以下条件在参考日历和数据之间创建内部联接。
构建视图
使用 Vertica - 它有 TIMESERIES 子句 - 不需要递归。
我会尝试下面的方法 - 并检查通用 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