如何在Impala / Hive中重新格式化多个不同的日期

时间:2019-05-11 18:59:34

标签: sql hive impala

在表中,存在以各种格式保存的日期。例如

19/Jun/1965     
30-Jun-1980
29-Mar-1970
Jun-12-1969

我希望它们全部以相同格式保存。我正在尝试将其分类为子集并解决每个个体的方法

select birthdate, 
case 
when birthdate like '%-%' then cast(unix_timestamp(birthdate, 'dd-MMM-yyyy') as timestamp) 
when birthdate like '%/%' then cast(unix_timestamp(birthdate, 'dd/MMM/yyyy') as timestamp) 
end from patientinfo;

但是,这可能会导致多个嵌套的大小写查询。

是否有更好的方法将所有数据转换为相同的日期格式?

2 个答案:

答案 0 :(得分:1)

是的。

您可以编写自己的UDF函数,其功能类似于this。 您需要遍历所有可能的格式,并尝试验证每种格式的数据。如果无效,请返回一条消息或一个默认值,例如“ 1000-01-01”。

您可以看到here如何构建UDF函数。

祝你好运!

答案 1 :(得分:0)

正如F.Lazarescu指出的那样,您可以使用“外部”工具作为UDF(如果您习惯使用它们以及Java或C ++之类的语言,可能会更容易),也可以只使用正则表达式。

Impala为此提供了regexp_extract。我做了一个查询,您可以将其用于您上面所述的日期。

如果您的日期可能具有其他语法,则应将其添加到正则表达式中:

select date_time,
case
when 
    -- If it starts with a number(day)
    regexp_extract(date_time, '^(\\d+).*?', 1)!='' THEN
    cast(unix_timestamp(
            concat(
            regexp_extract(date_time, '^(\\d+).*?', 1),-- Day
            '/',
            -- Extract and convert the month
            case 
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Jan' then '01'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Feb' then '02'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Mar' then '03'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Apr' then '04'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='May' then '05'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Jun' then '06'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Jul' then '07'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Aug' then '08'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Sep' then '09'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Oct' then '10'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Nov' then '11'
            when 
            regexp_extract(date_time, '([a-zA-Z]+?)', 1)='Dec' then '12'
            else null 
            end,
            '/',
            regexp_extract(fecha, '(\\d+)$', 1)
            ),
        'dd/MM/yyyy') as timestamp)

WHEN 
        -- If it starts with an String (month)
        regexp_extract(date_time, '^([a-zA-Z]+).*?', 1) !='' then 
        cast(unix_timestamp(
            concat(
            regexp_extract(date_time, '(\\d+)', 1),-- Day
            '/',
            case 
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Jan' then '01'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Feb' then '02'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Mar' then '03'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Apr' then '04'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='May' then '05'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Jun' then '06'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Jul' then '07'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Aug' then '08'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Sep' then '09'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Oct' then '10'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Nov' then '11'
            when 
            regexp_extract(date_time, '^([a-zA-Z]+).*?', 1)='Dec' then '12'
            else null 
            end,
            '/',
            regexp_extract(date_time, '(\\d+)$', 1)),
        'dd/MM/yyyy') as timestamp)
else null 
end as converted_datetime
from mytable;

希望有帮助。