使用Hive / Pig填充不存在的数据

时间:2018-03-21 10:13:18

标签: hive apache-pig generate

我有一个具有以下结构的配置单元表:

id1, id2, year, value 
1, 1, 2000, 20
1, 1, 2002, 23
1, 1, 2003, 24
1, 2, 1999, 34
1, 2, 2000, 35
1, 2, 2001, 37
2, 3, 2005, 50
2, 3, 2006, 56
2, 3, 2008, 60

我有2个ID标识'用户',对于每个用户和年份我有一个值,但有几年没有值没有出现在表中。我想为每个id [id1,id2]和年份(考虑最小和最大年份之间的所有年份)添加一个值,使用上一年的值,以防一年不存在。因此表格应该成为:

id1, id2, year, value 
1, 1, 2000, 20
1, 1, 2001, 20
1, 1, 2002, 23
1, 1, 2003, 24
1, 2, 1999, 34
1, 2, 2000, 35
1, 2, 2001, 37
2, 3, 2005, 50
2, 3, 2006, 56
2, 3, 2007, 56
2, 3, 2008, 60

我需要在蜂巢或猪身上做这件事,或者在最坏的情况下我可以用火花去做

感谢,

2 个答案:

答案 0 :(得分:0)

如果可以将年份存储为表格,则可以获得最佳效果。

using System;
using System.Net;
using System.Net.Sockets;

    private static readonly IPEndPoint DefaultLoopbackEndpoint = new IPEndPoint(IPAddress.Loopback, port: 0);

    public static int GetAvailablePort()
    {
        using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            socket.Bind(DefaultLoopbackEndpoint);
            return ((IPEndPoint)socket.LocalEndPoint).Port;
        }
    }

1)使用此表格,id可以交叉连接以生成所有年份组合,然后create table dbname.years location 'hdfs_location' as select 2000 as yr union all select 2001 as yr --include as many years as possible 原始表格。

2)然后将行分类为组,因此上一步中的left join值(id表的原始表中缺少的年份)被赋予与先前非空值相同的组。这是通过运行总和来完成的。 运行子查询以查看如何分配组。

3)此后,为每个id1,id2,组合组合选择null

max

答案 1 :(得分:0)

我会在使用临时表时执行此操作。每个id1和id2的年份不同,因此我将为每个id1,id2创建一系列年份,而不是为所有人创建一系列年份。 1)获得每个id1,id2的最小年份和最大年份。调用此series_dtes表 2)左手连接到手边的表(我称之为cal_date) 3)从组合的series_dtes表和cal_date表中创建临时表。这将填写每个id1缺失的年份,id2表示2001年和2007年。 4)使用滞后函数填写2001年和2007年的缺失值。

create table tmp as 
with  series_dtes as (
select id1, id2, (t.min_dt+pe.idx) as series_year
from (select id1, id2, min(year) as min_dt, max(year) as max_dt from cal_date group by id1, id2) t
lateral view posexplode(split(space(t.max_dt-t.min_dt),' ')) pe as idx, dte)
select dte.id1, dte.id2, dte.series_year, t.value
from series_dtes dte
left join cal_date  t
on dte.series_year=t.year and t.id1=dte.id1 and t.id2=dte.id2
order by dte.id1, dte.id2, dte.series_year;

select id1, id2, series_year as year, 
(case when value is null then (lag(value) over (partition by id1,id2 order by series_year)) else value end) as value
from tmp;

Result:
id1     id2     year    value
1       1       2000    20
1       1       2001    20
1       1       2002    23
1       1       2003    24
1       2       1999    34
1       2       2000    35
1       2       2001    37
2       3       2005    50
2       3       2006    56
2       3       2007    56
2       3       2008    60