hive 补全某字段的空值,取字段上一条非空记录的值

一、问题

我们经过遇到这样的问题,要补全一个表某列的空值,策略是按某个规则排序后,取上一个非空的值替代。

二、思路

1、首先分组获取行号

2、找到被替代值所在的行号,以及下一个替代值的行号

3、把开始行号到下一个替代值行号的区间(左闭右开区间)数组展开,得到被替代值在每个行的值

4、原表join3生成的表

三、实现

1、先做一个测试表,有三列字段:uid,time,event。分别代表用户在什么时候发生什么事件。

数据如下:

uid	time	event
1	2018-12-02 11:00:29	A
1	2018-12-02 11:00:30	""
1	2018-12-02 11:00:31	B
1	2018-12-02 11:00:32	""
1	2018-12-02 11:00:33	""
2	2018-12-02 11:00:40	B
2	2018-12-02 11:00:41	""
2	2018-12-02 11:00:42	C
2	2018-12-02 11:00:44	""

现在想按照前面非空的值补全空值,即把事件列的空值补成 A B C

2、直接上代码

--udf
add jar udf-1.1.jar;
create temporary function get_range as 'com.hive.udf.Range';

with all_data as (
    select 
        a.*
        --对每个用户分组获取记录排序
        ,row_number() over (partition by uid order by time asc) as rank
        --对每个用户分组获取总记录数
        ,count(1) over (partition by uid) as cnt
    from test_table a 
)

select 
    a.uid
    ,a.time
    ,b.event
from all_data a
left join (
    select 
        uid,event,rank 
    from (
        select 
            uid
            ,event
            ,rank as start_rank
            --获取每个用户下一个不为空的event所在行数,最后一行获取到rank为null,故用cnt+1代替
            ,cast(coalesce(lead(rank) over(partition by uid order by rank asc),cnt+1) as int) as next_rank
        from all_data
        --过滤出event不为空的记录
        where event is not null and event<>''
    ) a 
    --展开数组
    lateral view explode(get_range(start_rank,next_rank)) b as rank 
) b 
on a.uid = b.uid 
and a.rank = b.rank

3、上述过程使用了一个udf,类似python的range方法,返回一个数据范围的数组

package com.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.ArrayList;

public class Range extends UDF {

    public ArrayList<Integer> evaluate(Integer startNum, Integer endNum){
        if(startNum == null || endNum == null || startNum > endNum){
            return null;
        }
        ArrayList<Integer> list = new ArrayList<Integer>();

        for(int i = startNum; i < endNum; i++){
            list.add(i);
        }

        return list;
    }
}

4、输出结果如下

uid	time	event
1	2018-12-02 11:00:29	A
1	2018-12-02 11:00:30	A
1	2018-12-02 11:00:31	B
1	2018-12-02 11:00:32	B
1	2018-12-02 11:00:33	B
2	2018-12-02 11:00:40	B
2	2018-12-02 11:00:41	B
2	2018-12-02 11:00:42	C
2	2018-12-02 11:00:44	C
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值