簡體   English   中英

使用SQL Server或Vertica按日期/月將記錄按日期范圍轉換為記錄

[英]Turning Records by Date Range into Records by Day/Month Using SQL Server or Vertica

我可以使用SQL Server或Vertica作為DB和Tableau作為報告工具。 任何這些媒介的解決方案都會有所幫助。

數據資源:我有一個包含100條記錄的表(userActivity),結構為:User,StartDate,EndDate

需要:我有興趣按日和月編制報告,顯示“總活躍天數”,這意味着如果User1的范圍為'20180101'到'20180331',他們將在1月,2月和3月每天貢獻一天或者如果按月匯總,則為31天,28天和31天。

目標:我最終會將所有用戶的總活動天數作為輸出匯總,以實現每天/每月的單一總計。

這個報告將延續到永久性,所以我更喜歡那些沒有按日/月硬編碼CASE / IF-THEN語句的解決方案。

謝謝!

雖然遞歸CTE是這種情況的一個很好的候選者,但它可以單獨使用tableau來處理。 假設您擁有此數據,以下是生成視圖所需的步驟。

在此輸入圖像描述

  1. 創建一個包含所有預期日期的參考表。 即使你需要從01/01/2018到01/01/2043覆蓋25年,這仍然不到10k行。

在此輸入圖像描述

您需要兩個具有完全相同日期的列,因為Tableau不允許在同一列上存在多個連接條件。

  1. 使用以下條件在參考日歷和數據之間創建內部聯接。 在此輸入圖像描述

  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

解:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM