日期清洗的sql函数

 

sql语言是postgressql。

函数只处理了

中国格式 : xxxx年-xx月-xx日

美国格式: mm/dd/yyyy, September 04,1991, September 1991, sept 04, 1991

uunix格式: yyyy/mm/dd, yyyy/mm, 1991-01-1, 1991-1 , 1991-01

其他格式可以自行添加

预期的日期格式是: 1991/1/1 。 不能有0,即1991/01/01 是失败的

函数返回的是: " ‘预期格式’,年,月"

一、主要使用的内置函数是:

1. instr( ,'str1' , 'str2' , ) 。

查找str2在str1出现的位置。num是出现的次数,默认是1。例如num=2,就是str2在str1第二次出现的位置。start_position是起始的位置下标,默认是从头开始即 1。

若str2在str1找不到,则返回0

 instr('123456', '2')  -- 结果是: 2. 位置索引值是从1开始
     
 instr('123456', '2' , 2) -- 结果是0 , 因为2 只出现一次

2. substr(str1, start_position, )

截取字符串, 从str1 的 start_position开始截取, 截取长度是 length。length不填就是截取到字符串的最右边。

例如 start_position=2, length=3,  str1= ‘’12345678‘’

substr('123456', 2, 3) -- 结果是: 234. 因为postgres是下标索引是1开始
 
substr('123456', 1, 3) -- 结果是: 123. 因为postgres是下标索引是1开始
substr('123456', 0, 3) -- 结果是: 123. 0也当成1
 
substr('123456', 2) -- 结果是: 23456.  长度值不填,默认就是截取到最右边

3.  regexp_like(str1,str2)

查看str1 是否 符合 规则 str2.

str2是正则表达式: ^ 表示开头 ,$ 表示结尾。/d 表示数字 0-9,[0-9]也是表达数字,可读性更好。 | 是或的意思。

'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') 的规则就是, 19xx,18xx, 20xx 。xx代表数字的任意值

4. split_part(str1, str2, index)

华为gauss DB(DWS)中的字符串切分函数。 可以使用你自己sql相似的函数。

将 str1 按照 str2 切分, 并取切分后结果集合的第几个值。

-- 将'1,2,3'用 ','切分, 并取切分后结果的第二个值。 
split_part('1,2,3' , ',' , 2) -- 结果是2

5. trim()

去除字符串收尾的空格,避免影响 split_part 以空格切分字符串。

6. month()

返回月值, 确保没有0 。 因为清洗的预期是不要0

二、日期清洗函数

-- 返回 'birthday,birthday_year,birthday_month'
CREATE OR REPLACE FUNCTION aml.f_get_date_str(birthday_str character varying(500))
 RETURNS character varying
 LANGUAGE plpgsql
 STABLE NOT FENCED SHIPPABLE -- 华为gausDB DWS的独有, postgres不用
AS $$
DECLARE
  p_birthday_str VARCHAR2(500);
  text_var1 text;
  text_var2 text;
  text_var3 text;
BEGIN
  SELECT 
      CASE -- 处理只有年份数字的 1988 、1978 
           WHEN regexp_like (trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') > 0 
                then concat_ws(',', trim(birthday_str)
                                  , trim(birthday_str)
                                  , ' '
                               )
                               
           -- 处理1988/05/15 或 1988/5/15 , 或1988/5/5
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(\/)([1-9]|[0][1-9]|[1][0-2])(\/)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])$') > 0 
                then concat_ws(',', year(birthday_str) || '/' || month(birthday_str) || '/' || day(birthday_str)
                                  , year(birthday_str)
                                  , month(birthday_str)
                               )
           -- 处理1988/05,1988/5 ,  确保 没有0开头, 所以调用year,month函数再组装
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(\/)([1-9]|[0][1-9]|[1][0-2])$') > 0 
                then concat_ws(',', year(trim(birthday_str) || '/01') || '/' || month(trim(birthday_str) || '/01')
                                  , year(trim(birthday_str) || '/01')
                                  , month(trim(birthday_str) || '/01')
                               )
                               
            -- 处理mm/dd/yyyy
           WHEN regexp_like(trim(birthday_str),'^([1-9]|[0][1-9]|[1][0-2])(\/)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(\/)([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') > 0 
                then concat_ws(',', year(birthday_str) || '/' || month(birthday_str) || '/' || day(birthday_str)
                                  , year(birthday_str)
                                  , month(birthday_str)
                               )
           -- 处理mm/yyyy ,  确保 没有0开头, 所以调用year,month函数再组装
           WHEN regexp_like(trim(birthday_str),'^([1-9]|[0][1-9]|[1][0-2])(\/)([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') > 0 
                then concat_ws(',', year(replace(trim(birthday_str),'/','/01/')) || '/' || month(replace(trim(birthday_str),'/','/01/'))
                                  , year(replace(trim(birthday_str),'/','/01/'))
                                  , month(replace(trim(birthday_str),'/','/01/'))
                               )
                
           -- 处理中国格式,
           -- xxxx年xx月xx日,  -> yyyy/m/d
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(年)([1-9]|[0][1-9]|[1][0-2])(月)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(日)$') > 0
                then concat_ws(',', year(replace(replace(replace(birthday_str,'年','/'),'月','/'),'日','')) || '/' || month(replace(replace(replace(birthday_str,'年','/'),'月','/'),'日','')) || '/' || day(replace(replace(replace(birthday_str,'年','/'),'月','/'),'日',''))
                                  , year(replace(replace(replace(birthday_str,'年','/'),'月','/'),'日',''))  
                                  , month(replace(replace(replace(birthday_str,'年','/'),'月','/'),'日',''))
                               )
           -- xxxx年xx月  -> yyyy/m
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(年)([1-9]|[0][1-9]|[1][0-2])(月)$') > 0
                then concat_ws(',', year(trim(replace(replace(birthday_str,'年','/'),'月','/')) || '01') || '/' || month(trim(replace(replace(birthday_str,'年','/'),'月','/')) || '01') 
                                  , year(trim(replace(replace(birthday_str,'年','/'),'月','/')) || '01' ) 
                                  , month(trim(replace(replace(birthday_str,'年','/'),'月','/')) || '01') 
                              )
           -- xxxx年xx  -> yyyy/m
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(年)([1-9]|[0][1-9]|[1][0-2])$') > 0
                then concat_ws(',', year(trim(replace(birthday_str,'年','/')) || '/01') || '/' || month(trim(replace(birthday_str,'年','/')) || '/01') 
                                  , year(trim(replace(birthday_str,'年','/')) || '/01')
                                  , month(trim(replace(birthday_str,'年','/')) || '/01')
                               )
           -- xxxx年
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(年)$') > 0
                then concat_ws(',', replace(birthday_str,'年','')
                                  , replace(birthday_str,'年','')
                                  , ' ' )
           
           -- 处理1988-05-15 或 1988-5-15 , 或1988-5-5
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(\-)([1-9]|[0][1-9]|[1][0-2])(\-)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])$') > 0 
                then concat_ws(',', year(replace(birthday_str,'-','/')) || '/' || month(replace(birthday_str,'-','/')) || '/' || day(replace(birthday_str,'-','/'))
                                  , year(replace(birthday_str,'-','/'))  
                                  , month(replace(birthday_str,'-','/'))
                               )
           -- 处理1988-05
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])(\-)([1-9]|[0][1-9]|[1][0-2])$') > 0 
                then concat_ws(',', year(trim(replace(birthday_str,'-','/')) || '/01') || '/' || month(trim(replace(birthday_str,'-','/')) || '/01')
                                  , year(trim(replace(birthday_str,'-','/')) || '/01')  
                                  , month(trim(replace(birthday_str,'-','/')) || '/01')
                               )
                               
           -- 处理19880515
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])([0][1-9]|[1][0-2])([0][1-9]|[1-2][0-9]|[3][0-1])$') > 0 
                then concat_ws(',', year(birthday_str) || '/' || month(birthday_str)  || '/' || day(birthday_str) 
                                  , year(birthday_str)
                                  , month(birthday_str)
                               )
           -- 处理198805,20xx05 , 补齐日的值 例如:01
           WHEN regexp_like(trim(birthday_str),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])([0][1-9]|[1][0-2])$') > 0 
                then concat_ws(',', year(trim(birthday_str) || '01') || '/' || month(trim(birthday_str) || '01')
                                  , year(trim(birthday_str) || '01')
                                  , month(trim(birthday_str) || '01')
                               )
           
           -- 处理美国时间格式(英文),'September 04, 1952' ,'Sept 04, 1952', 'September, 1952' , 'Sept, 1952'
           WHEN trim(split_part(split_part(birthday_str,',',1),' ',1)) in ('January' ,'February' ,'March' , 'April' , 'May' , 'June' , 'July' , 'August' ,'September' ,'October' ,'November' ,'December', 'Jan' , 'Feb' , 'Mar' ,'Apr' , 'Aug' , 'Sept' , 'Oct' ,'Nov' , 'Dec') 
            and regexp_like(trim(split_part(birthday_str,',',2)),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') > 0 -- 判断年份值是否合理
            then 
                -- 'September 04, 1952' 
                case when regexp_like(trim(split_part(split_part(birthday_str,',',1),' ',2)),'^([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])$') > 0  -- 判断日份值是否合理
                          then concat_ws(',', year(birthday_str) || '/' || month(birthday_str) || '/' || day(birthday_str)
                                            , year(birthday_str)
                                            , month(birthday_str)
                                         )
                     --不完整,缺少日 'September, 1952'  。 补全日期后(日期数值随意,这里补01),利用函数 year, month,day
                     when split_part(split_part(birthday_str,',',1),' ',2) is null 
                          then concat_ws(',', year(replace(birthday_str, ',' , '01,')) || '/' || month(replace(birthday_str, ',' , '01,')) 
                                            , year(replace(birthday_str, ',' , '01,'))
                                            , month(replace(birthday_str, ',' ,'01,')) 
                                         )
                     end
                     
           --  ’September 1952‘ 格式
           WHEN trim(split_part(birthday_str,' ',1)) in ('January' ,'February' ,'March' , 'April' , 'May' , 'June' , 'July' , 'August' ,'September' ,'October' ,'November' ,'December', 'Jan' , 'Feb' , 'Mar' ,'Apr' , 'Aug' , 'Sept' , 'Oct' ,'Nov' , 'Dec') 
            and regexp_like(trim(split_part(birthday_str,' ',2)),'^([1][8-9][0-9][0-9]|[2][0][0-9][0-9])$') > 0 -- 判断年份值是否合理
            then concat_ws(',', year(replace(birthday_str, ' ' , ' 01,')) || '/' || month(replace(birthday_str, ' ' , ' 01,'))
                              , year(replace(birthday_str, ' ' , ' 01,'))
                              , month(replace(birthday_str, ' ' , ' 01,'))
                           )
           
           ELSE concat_ws(',', ' ', ' ', ' ')
      END birthday_year_month INTO p_birthday_str ;
  RETURN (p_birthday_str) ;
  EXCEPTION
     WHEN others THEN
       GET STACKED DIAGNOSTICS text_var1 = RETURNED_SQLSTATE  ,
                             text_var2 = MESSAGE_TEXT  ,
                             text_var3 = PG_EXCEPTION_DETAIL;
       RAISE NOTICE E'--- [已处理的 异常代码_RETURNED_SQLSTATE ] : %', text_var1;    -- 记录异常信息
       RAISE NOTICE E'--- [已处理的 异常简要信息_MESSAGE_TEXT ] : %', text_var2;
       RAISE NOTICE E'--- [已处理的 异常详细信息_PG_EXCEPTION_DETAIL ] : %', text_var3;
       
       RETURN (concat_ws(',', ' ', ' ',' '))  ;  -- 处理异常的日期数据,直接返回。 例如日和月值不匹配,1955-02-30
END $$
;

你可能感兴趣的:(存储组件,数据库)