生成日期时间范围

3

我希望生成一个日期时间戳数组,每个时间戳之间的步长为1小时。

示例:

[2018-01-01 10:00:00, 2018-01-01 11:00:00, 2018-01-01 12:00:00]
GENERATE_DATE_ARRAY函数可以实现我的需求,但不幸的是它只适用于天、周、月等日期粒度,而不支持更细的时间粒度。

有什么建议吗? 谢谢。

2个回答

2
您可以使用GENERATE_ARRAY函数与ARRAYTIMESTAMP_ADD函数来构建所需范围的数组。以下是一个示例:
SELECT
  ARRAY(
    SELECT TIMESTAMP_ADD('2018-01-01 10:00:00', INTERVAL x HOUR)
    FROM UNNEST(GENERATE_ARRAY(0, TIMESTAMP_DIFF('2018-01-01 12:00:00', '2018-01-01 10:00:00', HOUR))) AS x
  ) AS timestamps

如果您愿意,可以创建一个SQL UDF,然后调用它:

CREATE TEMP FUNCTION MakeRange(lower TIMESTAMP, upper TIMESTAMP) AS (
  ARRAY(
    SELECT TIMESTAMP_ADD(lower, INTERVAL x HOUR)
    FROM UNNEST(GENERATE_ARRAY(0, TIMESTAMP_DIFF(upper, lower, HOUR))) AS x
  )
);
SELECT MakeRange('2018-01-01 10:00:00', '2018-01-01 12:00:00') AS timestamps

你看,Elliott比我聪明多了。不过我还是更喜欢我的UDF;-) - Graham Polley
1
@GrahamPolley 我有一个优势,因为我规定并实现了 GENERATE_ARRAYGENERATE_DATE_ARRAY ;) 供以后参考,这是功能请求,要求例如 GENERATE_TIMESTAMP_ARRAY - Elliott Brossard
我无法与之竞争 ;-) - Graham Polley

1
我相信比我聪明的人会在SQL中找到一种方法来做到这一点(瞪眼米哈伊尔),但是可以考虑使用JavaScript UDF。

像这样:

CREATE TEMPORARY FUNCTION
  generate_stepped_timestamp_array(step FLOAT64,
    iterations FLOAT64)
  RETURNS ARRAY<TIMESTAMP>
  LANGUAGE js AS """
  var timestamps = [];
  var start = new Date('2018-01-01');
  for(i = 0; i < iterations; i++){
    start.setHours(start.getHours() + step);
    timestamps.push(new Date(start));
  }
  return timestamps;
  """;
SELECT
  generate_stepped_timestamp_array(1,
    24) AS stepped_array

enter image description here

显然,我不是JavaScript高手!在JS中实现这个功能可能有更好的方法。但是,希望您仍然能理解这个想法。

我在旅途中找到了this。顺便说一下,我认为类似GENERATE_DATETIME_ARRAY功能请求会受到热烈欢迎。


谢谢,但不幸的是我们无法使用UDF,因为它们有更严格的速率限制配额。感谢提供链接,我会尝试看看能否使用它。 - Tarlen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接