Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用SQL Server或Vertica将按日期范围的记录转换为按天/月的记录_Sql_Sql Server_Tsql_Tableau Api_Vertica - Fatal编程技术网

使用SQL Server或Vertica将按日期范围的记录转换为按天/月的记录

使用SQL Server或Vertica将按日期范围的记录转换为按天/月的记录,sql,sql-server,tsql,tableau-api,vertica,Sql,Sql Server,Tsql,Tableau Api,Vertica,我可以使用SQL Server或Vertica作为数据库,使用Tableau作为报告工具。任何一种介质中的溶液都会有帮助 数据资源: 我有一个包含100条记录的表(userActivity),结构为:User、StartDate、EndDate 需要: 我感兴趣的是按天和月编制显示“总活动天数”的报告,这意味着如果User1的范围为“20180101”到“20180331”,则他们将在1月、2月和3月的每一天贡献一天,或者如果按月合计,则为31、28和31天 目标: 我最终会将所有用户的总活动天

我可以使用SQL Server或Vertica作为数据库,使用Tableau作为报告工具。任何一种介质中的溶液都会有帮助

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

需要: 我感兴趣的是按天和月编制显示“总活动天数”的报告,这意味着如果User1的范围为“20180101”到“20180331”,则他们将在1月、2月和3月的每一天贡献一天,或者如果按月合计,则为31、28和31天

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

此报告将持续到永久,因此我更喜欢不按天/月硬编码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来处理。假设您有这些数据,下面是生成视图所需的步骤

  • 创建包含所有预期天数的参考表。即使您需要覆盖从2018年1月1日到2043年1月1日的25年,这仍然少于10000行

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

  • 使用以下条件在参考日历和数据之间创建内部联接。

  • 构建视图


  • 使用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。做得好!我假设有一个Tableau解决方案,但对我来说,Tableau的大部分内容仍然非常复杂。感谢您阐明此功能,Jose!顺便说一句,爱的详细描述@AndrewGlenn,很高兴这有帮助。这是一个很好的问题,我很喜欢回答它。虽然第一个解决方案对我来说是可行的(也是我设计的),但这个方案显然比其他方案要差,假设可以使用Tableau或Vertica。此外,如果数据集或数据源比我的更大或更复杂,我的SQL Server解决方案可能会面临挑战。到目前为止,我们有3个可行的选择!