【问题标题】:Turning Records by Date Range into Records by Day/Month Using SQL Server or Vertica使用 SQL Server 或 Vertica 将按日期范围的记录转换为按日/月的记录
【发布时间】:2018-11-15 19:44:01
【问题描述】:

我可以使用 SQL Server 或 Vertica 作为数据库,使用 Tableau 作为报告工具。在任何这些媒介中的解决方案都会有所帮助。

数据资源: 我有一个包含 100 条记录的表 (userActivity),其结构为:User、StartDate、EndDate

需要: 我有兴趣按天和月准备显示“总活跃天数”的报告,这意味着如果 User1 的范围为“20180101”到“20180331”,他们将在 1 月、2 月和 3 月或 31 的每一天贡献一天,如果按月汇总,则为 28 天和 31 天。

目标: 我最终将汇总所有用户的总活跃天数作为输出,以实现每天/每月的单一总数。

此报告将永久有效,因此我更喜欢不按天/月对 CASE/IF-THEN 语句进行硬编码的解决方案。

谢谢!

【问题讨论】:

  • 我相信我已经弄明白了! :) 我正在使用以下代码创建一个最终表格,每个用户每个活跃日有一条记录。然后,我将在 Tableau 中按天或按月计算这些。请看下文。

标签: sql sql-server tsql tableau-api vertica


【解决方案1】:

虽然递归 CTE 非常适合这种情况,但它可以单独使用 tableau 来处理。假设您有这些数据,以下是生成视图所需的步骤。

  1. 创建一个包含所有预期天数的参考表。即使您需要涵盖从 01/01/2018 到 01/01/2043 的 25 年,这仍然少于 10k 行。

您需要两个日期完全相同的列,因为 Tableau 不允许同一列上有多个连接条件。

  1. 使用以下标准在参考日历和数据之间创建内部联接。

  2. 构建视图

【讨论】:

  • 我认为 Tableau 解决方案是可用的,但对我来说,Tableau 的大部分内容仍然相当复杂。感谢您阐明此功能,Jose!
  • 喜欢详细的描述,顺便说一句!
  • @AndrewGlenn,很高兴它有帮助。这是一个很好的问题,我很乐意回答。
【解决方案2】:

使用 Vertica - 它有 TIMESERIES 子句 - 不需要递归。

我会尝试以下方法 - 并检查公用表表达式的中间结果,看看它是如何工作的......

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

【讨论】:

  • 优秀的基于 Vertica 的解决方案。我喜欢根据后端要求进行选择。在很多情况下,我也更喜欢使用 Vertica。干得好!
【解决方案3】:

解决方案:

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)

【讨论】:

  • 虽然是我可用的第一个解决方案(也是我设计的那个),但假设存在对 Tableau 或 Vertica 的访问权限,这个选项显然不如其他选项。此外,如果数据集或源比我的更大或更复杂,我的 SQL Server 解决方案可能会面临挑战。到目前为止,我们有 3 个可行的选项!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 2020-12-16
  • 2023-01-10
相关资源
最近更新 更多