关于hive时间的拆分(将两个时刻拆分成时间区间,做简单的操作)
今天有个同事问了一道面试题。面试题如下:
他的意思是将时间拆分成下面右边的样子,开始时间是整数,结束时间是多少就是多少。
看到这个题目第一眼感觉挺简单的,就是拆。
大概的思路如下:
(1)给的是字符串,需要将数据拼接,拆分成具体的日期时间格式,然后才能操作。同时对数据开始时间进行规整操作
(2)第二步,根据时刻只差,然后采用根据lateral view posexplode 爆炸函数,将一个一行数据,然后根据他的步长数据拆分成不用的行数据,
所谓的列转行数据。
(3)第三步,得到了拆分后的数据,似乎还是不能满足要求,这个时候我们就要用到我们经常使用到的连续性函数,lead.对这行的数据进行操作,
对相同的数据分组排序,升序操作,这样就能到到我们想要的数据,最后做一个简单的拼接,问题解决。
具体代码如下:
with mon as ( select '12:06-14:30' as date_time union all select '11:00-12:07' as date_time ) ,mon1 as ( select start_time, end_time, date_time, hour(end_time)-hour(start_time) as hour_gap from ( select concat('2021-11-23 ','',substr(split(date_time,'-')[0],0,2) ,':00',':00') as start_time, concat('2021-11-23 ','',split(date_time,'-')[1] ,':00') as end_time,date_time from mon ) a ) ,mon2 as ( select pos, start_time, end_time, date_time, from_unixtime(unix_timestamp(start_time)+pos*3600,'yyyy-MM-dd HH:mm:ss') as time_ll from mon1 t lateral view posexplode(split(space(hour_gap),' ')) tf as pos,val limit 5000 ) select a.date_time, case when a.time_ls is not null then concat(substr(time_ll,11,6),'-',substr(time_ls,11,6)) else concat(substr(time_ll,11,6),'-',substr(end_time,11,6)) end as time_lls from ( select a.*, lead(time_ll,1) over(partition by start_time,end_time order by pos ) as time_ls from mon2 a ) a
注意的点:hive的时间是通过 小时*60*60进行时间相加的。所以这里采用了pos*60*60的步长对时间进行操作,得到结果。