【问题标题】:BigQuery Date and Time Functions returning NULL on a timestamp columnBigQuery 日期和时间函数在时间戳列上返回 NULL
【发布时间】:2015-09-09 06:51:58
【问题描述】:

我正在使用 LAG() 和 LEAD() 从表中的一个时间戳列中提取 3 个时间戳列:timestamp、prev_timestamp、next_timestamp。我需要做一些简单的日期和时间格式化,但是当我在 prev_timestamp 或 next_timestamp 上使用 MONTH() 之类的函数时,它会返回 NULL。

结果列的架构类型是正确的 (TIMESTAMP),并且由于某种原因,常规时间戳日期和时间格式有效。如何使它正确返回所有 3 列的月份?

示例代码为时间戳列返回月份,为上一个和下一个时间戳列返回 NULL:

SELECT 
  MONTH(timestamp) AS month,
  MONTH(prev_timestamp) AS prev_month,
  MONTH(next_timestamp) AS next_month
FROM (
  SELECT
    timestamp,
    LAG(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) prev_timestamp,
    LEAD(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) next_timestamp
  FROM timestamp_table
  )

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    所以在测试和检查了几件事后,我实际上从Mikhail's answer 中得到启发,并意识到他的答案是不正确的,因为滞后/领先不会返回毫秒,而是微秒(为什么?这是任何人的猜测)。

    SELECT 
      MONTH(timestamp) AS month,
      MONTH(MSEC_TO_TIMESTAMP((prev_timestamp/1000))) AS prev_month,
      MONTH(MSEC_TO_TIMESTAMP((next_timestamp/1000))) AS next_month
    FROM (
      SELECT
        timestamp,
        LAG(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) prev_timestamp,
        LEAD(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) next_timestamp
      FROM timestamp_table
      )
    

    应该可以。我刚刚测试了创建一个包含三行时间戳的表。在没有 /1000 的情况下使用它,我的滞后/领先版本给出了不同的月份。我测试过,如果你不做除法,你最终会在第 47 个千年的某个地方结束。

    【讨论】:

    • 这看起来很有效 - 我仍然很好奇为什么它有效。我对导致我们必须从 MSEC 进行转换的类型转换有什么不明白的地方,这是什么时候发生的?
    • @AaronR 我不完全确定原因,但我认为在内部,为了节省空间,时间戳被保存为“自纪元以来的微秒”。 “Lead”和“Lag”函数可能会返回“无格式”,迫使我们使用该解决方法
    【解决方案2】:

    试试下面

    SELECT 
      MONTH(MSEC_TO_TIMESTAMP(timestamp)) AS month,
      MONTH(MSEC_TO_TIMESTAMP(prev_timestamp)) AS prev_month,
      MONTH(MSEC_TO_TIMESTAMP(next_timestamp)) AS next_month
    FROM (
      SELECT
        timestamp,
        LAG(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) prev_timestamp,
        LEAD(timestamp,1) OVER (PARTITION BY id ORDER BY timestamp) next_timestamp
      FROM timestamp_table
      )
    

    【讨论】:

    • 用时间戳尝试这个(我做了一个“选择CURRENT_TIMESTAMP()”作为我的测试表)给出了一个类型错误......不确定这是这里的解决方案。明白了,算了。第一个时间戳不需要 MSEC,因为它确实返回了一个时间戳。这是其他需要改变的人
    猜你喜欢
    • 2018-05-22
    • 2018-09-27
    • 2015-10-23
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多