首页 > 解决方案 > BigQuery 的问题不尊重 WHEN 语句

问题描述

如果我尝试解析和更正字符串结构中的某些日期,我有以下查询(小节),9999 是指循环日期,而 9996 是指仅对闰年有效的循环日期。

将 9999 年更改为当前周期的 FIX_YEAR 函数应该忽略任何 9996 年输入,但是当我使用示例字符串运行查询时,它不会被忽略。


任何想法可能是什么问题?

谢谢!

CREATE TEMP FUNCTION
  FIX_YEAR(val STRUCT<after DATE,
    before DATE>) AS (
    CASE
      WHEN (EXTRACT(YEAR FROM val.after) = 9999) AND (EXTRACT(YEAR FROM val.before) = 9999) THEN ( CASE
        WHEN DATE(EXTRACT(YEAR
        FROM
          CURRENT_DATE), EXTRACT(MONTH
        FROM
          val.after), EXTRACT(DAY
        FROM
          val.after)) <= DATE(EXTRACT(YEAR
        FROM
          CURRENT_DATE), EXTRACT(MONTH
        FROM
          val.before), EXTRACT(DAY
        FROM
          val.before)) THEN (
        CASE
          WHEN DATE(EXTRACT(YEAR FROM CURRENT_DATE), EXTRACT(MONTH FROM val.before), EXTRACT(DAY FROM val.before)) < CURRENT_DATE THEN ( [STRUCT ( DATE(EXTRACT(YEAR FROM CURRENT_DATE) + 1, EXTRACT(MONTH FROM val.after), EXTRACT(DAY FROM val.after)) AS after, DATE(EXTRACT(YEAR FROM CURRENT_DATE) + 1, EXTRACT(MONTH FROM val.before), EXTRACT(DAY FROM val.before)) AS before )] )
          WHEN DATE_DIFF( DATE(EXTRACT(YEAR
            FROM
              CURRENT_DATE) + 1, EXTRACT(MONTH
            FROM
              val.after), EXTRACT(DAY
            FROM
              val.after)), CURRENT_DATE, DAY) <= 330 THEN ( [STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE) + 1, EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE) + 1, EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before ),
          STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before )] )
        ELSE
        ( [STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before )] )
      END
        )
      ELSE
      [val]
    END
      )
    ELSE
    [val]
  END
    );
CREATE TEMP FUNCTION
  EXTRACT_SEASONAL_DATES(season_text STRING) AS ( FIX_YEAR ( STRUCT ( PARSE_DATE('%Y-%m-%d',
          COALESCE(REGEXP_EXTRACT(season_text, r'^(\d{4}-\d{2}-\d{2})@'),
            '9999-12-31')) AS after,
        PARSE_DATE('%Y-%m-%d',
          COALESCE(REGEXP_EXTRACT(season_text, r'@(\d{4}-\d{2}-\d{2})$'),
            '9999-12-31')) AS before ) ) );
SELECT
  EXTRACT_SEASONAL_DATES(season_inbound) season_inbound
FROM (
  SELECT
    "9999-02-01@9999-02-02,9999-02-09@9999-02-09,9999-02-15@9999-02-17,9999-02-22@9999-02-24,9996-02-29@9999-03-02,9999-04-08@9999-04-13,9999-05-03@9999-05-04,9999-05-24@9999-05-25,9999-07-01@9999-07-06,9999-07-15@9999-07-17,9999-07-19@9999-07-20,9999-07-24@9999-07-29,9999-08-16@9999-08-17,9999-09-12@9999-09-23,9999-11-02@9999-11-02" AS season_inbound)
CROSS JOIN
  UNNEST(SPLIT(season_inbound, ',')) season_inbound

标签: sqlgoogle-bigquery

解决方案


我认为代码运行良好。

正如@FelipeHoffa 在第一条评论中提到的那样,该问题与无效日期的错误有关,对于您的情况“9996-02-29@9999-03-02”,这是一个无效日期,因为您的函数将其转换为“2019 -02-29”该日期不存在,因此 BigQuery 会引发错误消息“输入计算为无效日期:2019-02-29”。

我已将此日期修改为“9996-02-28@9999-03-02”,一切正常。

CREATE TEMP FUNCTION
  FIX_YEAR(val STRUCT<after DATE,
    before DATE>) AS (
    CASE
      WHEN (EXTRACT(YEAR FROM val.after) = 9999) AND (EXTRACT(YEAR FROM val.before) = 9999) THEN ( CASE
        WHEN DATE(EXTRACT(YEAR
        FROM
          CURRENT_DATE), EXTRACT(MONTH
        FROM
          val.after), EXTRACT(DAY
        FROM
          val.after)) <= DATE(EXTRACT(YEAR
        FROM
          CURRENT_DATE), EXTRACT(MONTH
        FROM
          val.before), EXTRACT(DAY
        FROM
          val.before)) THEN (
        CASE
          WHEN DATE(EXTRACT(YEAR FROM CURRENT_DATE), EXTRACT(MONTH FROM val.before), EXTRACT(DAY FROM val.before)) < CURRENT_DATE THEN ( [STRUCT ( DATE(EXTRACT(YEAR FROM CURRENT_DATE) + 1, EXTRACT(MONTH FROM val.after), EXTRACT(DAY FROM val.after)) AS after, DATE(EXTRACT(YEAR FROM CURRENT_DATE) + 1, EXTRACT(MONTH FROM val.before), EXTRACT(DAY FROM val.before)) AS before )] )
          WHEN DATE_DIFF( DATE(EXTRACT(YEAR
            FROM
              CURRENT_DATE) + 1, EXTRACT(MONTH
            FROM
              val.after), EXTRACT(DAY
            FROM
              val.after)), CURRENT_DATE, DAY) <= 330 THEN ( [STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE) + 1, EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE) + 1, EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before ),
          STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before )] )
        ELSE
        ( [STRUCT ( DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.after), EXTRACT(DAY
              FROM
                val.after)) AS after,
            DATE(EXTRACT(YEAR
              FROM
                CURRENT_DATE), EXTRACT(MONTH
              FROM
                val.before), EXTRACT(DAY
              FROM
                val.before)) AS before )] )
      END
        )
      ELSE
      [val]
    END
      )
    ELSE
    [val]
  END
    );
CREATE TEMP FUNCTION
  EXTRACT_SEASONAL_DATES(season_text STRING) AS ( FIX_YEAR ( STRUCT ( PARSE_DATE('%Y-%m-%d',
          COALESCE(REGEXP_EXTRACT(season_text, r'^(\d{4}-\d{2}-\d{2})@'),
            '9999-12-31')) AS after,
        PARSE_DATE('%Y-%m-%d',
          COALESCE(REGEXP_EXTRACT(season_text, r'@(\d{4}-\d{2}-\d{2})$'),
            '9999-12-31')) AS before ) ) );
SELECT
  EXTRACT_SEASONAL_DATES(season_inbound) season_inbound
FROM (
  SELECT
    "9999-02-01@9999-02-02,9999-02-09@9999-02-09,9999-02-15@9999-02-17,9999-02-22@9999-02-24,9996-02-28@9999-03-02,9999-04-08@9999-04-13,9999-05-03@9999-05-04,9999-05-24@9999-05-25,9999-07-01@9999-07-06,9999-07-15@9999-07-17,9999-07-19@9999-07-20,9999-07-24@9999-07-29,9999-08-16@9999-08-17,9999-09-12@9999-09-23,9999-11-02@9999-11-02" AS season_inbound)
CROSS JOIN
  UNNEST(SPLIT(season_inbound, ',')) season_inbound

得到这个结果:

在此处输入图像描述


推荐阅读