【问题标题】:Vertica date series is starting one month before specified dateVertica 日期系列从指定日期前一个月开始
【发布时间】:2015-11-12 14:35:02
【问题描述】:

我使用 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”或 1 月的任何时间,我最终会得到一个额外的条目,即 2014-12-01。就其本身而言,这个错误(或任何你想称之为意外行为的东西)很容易规避(从 2 月开始),但我不得不承认我的好奇心被激发了。为什么系列赛在我指定的日期前一个月开始?

编辑:好的,在阅读了 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 日运行此查询,我想知道它会如何表现。我想我只能等到 12 月才能看到,除非有人知道如何让时间序列以允许我对其进行测试的方式运行。

编辑:好的,所以在尝试了许多不同的日期组合之后,我能够确定系列开始的日期会根据您指定的日期而变化。这引起了很多问题……直到我们决定走简单的路。我们没有使用一个月间隔,而是使用天间隔,并且每个月只选择一个特定的日子。更简单,它一直有效。这是最终的查询:

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

【问题讨论】:

  • 你应该建立一个calendar table否则,一个SQL解决方案是可用的here
  • 感谢 Kermit,但这不是我要问的。我在询问列表开头出现的额外“2014-12-01”。就目前而言,促使需要构建此查询的问题已经解决。

标签: sql vertica


【解决方案1】:

我认为归结为文档中的以下声明: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 天。如果您要使用超过几年,这显然会出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 2012-10-27
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2017-01-16
    相关资源
    最近更新 更多