【问题标题】:Bigquery: convert abbreviated month string to numberBigquery:将缩写的月份字符串转换为数字
【发布时间】:2016-09-09 08:38:08
【问题描述】:

在大查询中:

如何将缩写的月份转换为月份的数字?

输入可能是:01-feb-1980 或 01-Feb-1980 或 01-FEB-1980 输出:02

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    这里是纯标准 SQL 解决方案,它不需要 UDF,并且依赖于 PARSE_DATE 函数,尤其是 %b format specifier

    select extract(month from parse_date('%d-%b-%Y', d)) from
    unnest(['01-FEB-1980', '01-feb-1980', '01-Feb-1980']) d
    

    返回2, 2, 2

    【讨论】:

    • 我现在清楚地看到over-engineering 是什么意思! :o) 谢谢你,莫莎!仍然喜欢尝试:o)
    【解决方案2】:

    有时,当日期集成不是标准格式时,它们可能会很棘手。

    这是其中一种情况,日期的月份类似于 01-Feb-1980 或 01-FEB-1980 或 01-feb-1980

    select 
    month_str as month_abbriviation,
    (case 
    when upper(month_str) = 'JAN' then '01' 
    when upper(month_str) = 'FEB' then '02' 
    when upper(month_str) = 'MAR' then '03' 
    when upper(month_str) = 'APR' then '04' 
    when upper(month_str) = 'MAY' then '05' 
    when upper(month_str) = 'JUN' then '06' 
    when upper(month_str) = 'JUL' then '07' 
    when upper(month_str) = 'AUG' then '08' 
    when upper(month_str) = 'SEP' then '09' 
    when upper(month_str) = 'OCT' then '10' 
    when upper(month_str) = 'NOV' then '11' 
    when upper(month_str) = 'DEC' then '12' 
    end) as month_number
    from (select regexp_extract('01-Feb-1980', r'..-(...)-....') as month_str);`
    

    【讨论】:

      【解决方案3】:

      标准 SQL 有一个很好的特性,叫做 Scalar UDF
      目前支持两种语言 - JavaScript UDFSQL UDF

      下面的示例通过在主查询之外提取转换逻辑来帮助清理主代码,因此代码变得更好/更易于阅读和维护(绝对是个人喜好问题

      CREATE TEMPORARY FUNCTION MONTH_STRING(x STRING)
      RETURNS STRING AS (LOWER(REGEXP_EXTRACT(x, r'-(...)-')));
      
      CREATE TEMPORARY FUNCTION MONTH_TO_NUMBER(x STRING)
      RETURNS STRING AS (CASE 
        WHEN x='jan' THEN '01' WHEN x='feb' THEN '02' WHEN x='mar' THEN '03' WHEN x='apr' THEN '04' 
        WHEN x='may' THEN '05' WHEN x='jun' THEN '06' WHEN x='jul' THEN '07' WHEN x='aug' THEN '08' 
        WHEN x='sep' THEN '09' WHEN x='oct' THEN '10' WHEN x='nov' THEN '11' WHEN x='dec' THEN '12' 
      END );
      
      WITH yourTable AS (
        SELECT '1-feb-1980'AS dt UNION ALL
        SELECT '01-Mar-1980' AS dt UNION ALL
        SELECT '01-SEP-1980' AS dt
      )
      SELECT 
        dt, 
        MONTH_TO_NUMBER(MONTH_STRING(dt)) AS month_number
      FROM yourTable
      

      选项 2

      不知何故,我不喜欢 MONTH_TO_NUMBER() 函数,因为它对 WHEN THEN 事物的影响很大

      这个函数的以下版本对我来说看起来更优雅(说实话不太确定 - 仍然看起来很重 - 但我还是喜欢尝试

      CREATE TEMPORARY FUNCTION MONTH_TO_NUMBER(x STRING)
      RETURNS STRING AS ((
        SELECT SUBSTR(CAST(101 + num AS STRING), 2) FROM  
        UNNEST(['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']) AS list 
        WITH OFFSET AS num WHERE list = x));
      

      选项 3

      返回所有没有UDF的内联

      WITH yourTable AS (
        SELECT '1-feb-1980'AS dt UNION ALL
        SELECT '01-Mar-1980' AS dt UNION ALL
        SELECT '01-SEP-1980' AS dt
      )
      SELECT 
        dt,
        (SELECT SUBSTR(CAST(101 + num AS STRING), 2) 
         FROM UNNEST(['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']) AS list 
         WITH OFFSET AS num 
         WHERE list = LOWER(REGEXP_EXTRACT(dt, r'-(...)-'))) AS month_number
      FROM yourTable
      

      【讨论】:

        猜你喜欢
        • 2014-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多