这两天碰到了一个小坑,起因是接手了一个数据 pipeline,然后我需要加一点新的功能。
这个功能需要取原来的表 left join 另外一张表取一个字段,然后有一个 where 条件是需要判定时间段是否符合,即 date between start_date and end_date。然而不知道同事脑子里装的什么,原来的表是把日期按‘yyyyMMdd'的格式存成字符串。
说不出话,于是面向爆栈编程,看到两种转换方法:

cast(concat(substr(STR_DMY,1,4), '-', substr(STR_DMY,5,2), '-', substr(STR_DMY,7,2))as date

from_unixtime(unix_timestamp('20180901' , 'yyyyMMdd'))

这还用说么,当然是第二种优雅。随后是漫长的 map reduce 过程。由于两张表都巨大无比,一个2B条记录一个10M条记录,运行时间高达两个多小时。
好不容易跑完,发现一个问题——新做的表比原来的表记录要少。经过漫长的排查(毕竟运行时间巨长),我终于发现,有一部分uid的所有记录都丢失了。
查其时间段发现,大概长这样—— (2018-08-01,2018-09-01) (2018-09-02, 2099-01-01)。看起来没什么问题,然而那是对于使用date类型的正常人而言的。
from_unixtime(unix_timestamp('20180901' , 'yyyyMMdd')) 输出的类型是 datetime 而不是 date,这就导致了

from_unixtime(unix_timestamp('20180901' , 'yyyyMMdd')) between '2018-08-01' and '2018-09-01' 
from_unixtime(unix_timestamp('20180901' , 'yyyyMMdd')) between '2018-09-02' and '2099-01-01' 

全部返回false。
至此,破案。

这是个小坑,但是浪费了我挺长时间,算是留个纪念,也算我求你们——别特么用字符串存时间了!