将未来日期的集合列表添加到SQL查询中的行

时间:2017-03-22 23:24:09

标签: sql vertica

所以我正在为客户做一个队列分析,其中一个群组是在同一个月开始使用该产品的一群人。然后,我跟踪每个队列的总使用情况,直到现在为止每个月。

例如,第一个"队列月份"是2012年1月,那么我已经"使用了几个月" 1月12日,2月12日,3月12日,...,3月17日(本月)。一栏是"队列月",另一栏是"使用月"。每个后续的队列月份都会重复此过程。该表看起来像:

Jan 12 | Jan 12  
Jan 12 | Feb 12  
...   
Jan 12 | Mar 17  
Feb 12 | Feb 12  
Feb 12 | Mar 12  
...  
Feb 12 | Mar 17  
...  
Feb 17 | Feb 17  
Feb 17 | Mar 17  
Mar 17 | Mar 17  

问题出现了,因为我想对现有和未来的同类群组进行一年的预测。 这意味着对于1月12日的队列,我想做4月17日到3月18日的预测。 我还想对4月17日至4月18日的4月17日队列(目前还不存在)进行预测。直到3月18日对3月18日队列进行预测。 我可以处理预测,不用担心。

我的问题是我无法弄清楚如何在(4月17日〜3月17日)的使用月份和#34;每个群组切换之前的列。 我还需要在4月17日至3月18日添加同类群组,并在这些未来队列中列出(4月17日至3月17日)此列表的适用部分。

所以我希望桌子看起来像:

Jan 12 | Jan 12  
Jan 12 | Feb 12  
...   
Jan 12 | Mar 17  
Jan 12 | Apr 17  
..    
Jan 12 | Mar 18  
Feb 12 | Feb 12  
Feb 12 | Mar 12  
...  
Feb 12 | Mar 17  
Feb 12 | Apr 17  
...  
Feb 12 | Mar 18  
...    
...    
Feb 17 | Feb 17  
Feb 17 | Mar 17    
...  
Feb 17 | Mar 18  
Mar 17 | Mar 17    
...  
Mar 17 | Mar 18  

我知道要想到的第一个解决方案是创建一个包含1月12日到3月18日所有日期的列表,将其交叉连接到自身,然后将外部联接保留到我当前的表中(其中同类/使用)月份从1月12日到3月17日。但是,这不可扩展。

有没有办法可以迭代地添加下一年的月份列表?

我正在使用HP Vertica,如果绝对必要,可以使用Presto或Hive

1 个答案:

答案 0 :(得分:0)

我认为您应该使用下面的查询来创建一个临时表,并将其与其余查询一起加入。我不能在SQL中以程序方式做任何事情,我很害怕。如果没有CROSS JOIN,你将无法逃脱。但是在这里,您将CROSS JOIN限制为您需要的第一个月对的生成。

这里是:

WITH
-- create a list of integers from 0 to 100 using the TIMESERIES clause
i(i) AS (
SELECT dt::DATE - '2000-01-01'::DATE
FROM ( 
          SELECT '2000-01-01'::DATE +   0 
UNION ALL SELECT '2000-01-01'::DATE + 100
) d(d)
TIMESERIES dt AS '1 day' OVER(ORDER BY d::TIMESTAMP)
)
,
-- limits are Jan-2012 to the first of the current month plus one year
month_limits(month_limit) AS (
          SELECT '2012-01-01'::DATE
UNION ALL SELECT ADD_MONTHS(TRUNC(CURRENT_DATE,'MONTH'),12)
)
-- create the list of possible months as a CROSS JOIN of the i table
-- containing the integers and the month_limits table, using ADD_MONTHS()
-- and the smallest and greatest month of the month limits
,month_list AS (
SELECT
  ADD_MONTHS(MIN(month_limit),i) AS month_first
FROM month_limits CROSS JOIN i
GROUP BY i
HAVING ADD_MONTHS(MIN(month_limit),i) <= (
  SELECT MAX(month_limit) FROM month_limits
  )
)
-- finally, CROSS JOIN the obtained month list with itself with the
-- filters needed.
SELECT
  cohort.month_first AS cohort_month
, use.month_first    AS use_month
FROM month_list AS cohort
CROSS JOIN month_list AS use
WHERE use.month_first >= cohort.month_first
ORDER BY 1,2
;