Vertica日期系列在指定日期

时间:2015-11-12 14:35:02

标签: sql vertica

我使用Vertica数据库,我需要进行一个查询,给定两个日期,会给出一个所述日期之间所有月份的列表。例如,如果我要提供查询2015-01-01和2015-12-31,它会输出以下列表:

2015-01-01
2015-02-01
2015-03-01
2015-04-01
2015-05-01
2015-06-01
2015-07-01
2015-08-01
2015-09-01
2015-10-01
2015-11-01
2015-12-01

经过一番挖掘,我发现了以下查询:

SELECT date_trunc('MONTH', ts)::date as Mois
FROM 
(
    SELECT '2015-01-01'::TIMESTAMP as tm
    UNION
    SELECT '2015-12-31'::TIMESTAMP as tm
) as t
TIMESERIES ts as '1 month' OVER (ORDER BY tm)

此查询有效,并为我提供以下输出:

2014-12-01
2015-01-01
2015-02-01
2015-03-01
2015-04-01
2015-05-01
2015-06-01
2015-07-01
2015-08-01
2015-09-01
2015-10-01
2015-11-01
2015-12-01

正如您所看到的那样,通过为查询提供开始日期' 2015-01-01'或者在一月份的任何地方,我最终会得到一个额外的条目,即2014-12-01。就其本身而言,这个错误(或任何你想称之为意外行为的东西)很容易规避(只是从二月开始),但我不得不承认我的好奇心。为什么系列在我指定的日期之前一个月开始呢?

编辑:好的,在阅读了Kimbo的警告并确认确实长时间最终会导致问题后,我能够提出以下查询,正确地重新调整日期。

SELECT ts as originalMonth, 
ts + 
    (
        mod
        (
            day(first_value(ts) over (order by ts)) - day(ts) + day(last_day(ts)), 
            day(last_day(ts))
        )
    ) as adjustedMonth
FROM 
(
    SELECT ts
    FROM 
    (
        SELECT '2015-01-01'::TIMESTAMP as tm
        UNION
        SELECT '2018-12-31'::TIMESTAMP as tm
    ) as t
    TIMESERIES ts as '1 month' OVER (ORDER BY tm)
) as temp

我唯一的问题是我无法控制系列第一张唱片的第一天。它由Vertica自动设置为当天。因此,如果我在本月31日运行此查询,我想知道它是如何表现的。我想我必须等到十二月才能看到,除非有人知道如何让时间序列以一种允许我测试它的方式行事。

编辑:好的,所以在尝试了许多不同的日期组合后,我能够确定系列开始的日期会根据您指定的日期而变化。这导致了很多问题......直到我们决定采用简单的方法。我们使用了一天的时间间隔,而不是每月使用一个月,而是每月只选择一个特定的日期。更简单,它一直有效。这是最后的查询:

SELECT ts as originalMonth
FROM 
(
    SELECT ts
    FROM 
    (
        SELECT '2000-02-01'::TIMESTAMP as tm
        UNION
        SELECT '2018-12-31'::TIMESTAMP as tm
    ) as t
    TIMESERIES ts as '1 day' OVER (ORDER BY tm)
) as temp
where day(ts) = 1

1 个答案:

答案 0 :(得分:3)

我认为这可以归结为文档中的这句话:http://my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/SQLReferenceManual/Statements/SELECT/TIMESERIESClause.htm

  

TIME_SLICE可以返回时间片的开始或结束时间,具体取决于   在其第四个输入参数(start_or_end)的值上。 TIMESERIES,   另一方面,始终返回每个时间片的开始时间。

当您定义具有某个开始日期(例如2015-01-01)的时间间隔时,TIMESERIES ts AS '1 month'将为其第一次创建一个切片,该切片在该第一个数据点之前1个月开始,所以2014-12-01。当您执行DATE_TRUNC('MON', ts)时,即使您的开始日期为2014-12-01,也可以设置第一个日期值为2015-01-03

e:我想再发出一次警告 - 我认为你使用DATE_TRUNC可以实现你所需要的。但是,从文档:与TIME_SLICE不同,[TIMESERIES] length_and_time_unit_expr中表示的时间片长度和时间单位必须是常量,因此时间片中的间隙是明确定义的。这意味着'1个月'实际上是30天。如果你要去的时间超过两年,这显然会有问题。