今天有個同事問了一道面試題。面試題如下:
他的意思是將時間拆分成下面右邊的樣子,開始時間是整數,結束時間是多少就是多少。
看到這個題目第一眼感覺挺簡單的,就是拆。
大概的思路如下:
(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的步長對時間進行操作,得到結果。