HIVE相当于FIRST和LAST

时间:2015-08-12 16:53:22

标签: hadoop hive sas hiveql

我有一个包含3列的表格:

table1: ID, CODE, RESULT, RESULT2, RESULT3

我有这个SAS代码:

data table1
   set table1;
   BY ID, CODE;
   IF FIRST.CODE and RESULT='A' THEN OUTPUT;
   ELSE IF LAST.CODE and RESULT NE 'A' THEN OUTPUT;
RUN;

因此,我们按ID和CODE对数据进行分组,然后在满足某些条件的情况下写入数据集。我想编写一个hive查询来复制它。这就是我所拥有的:

proc sql;
   create table temp as
   select *, row_number() over (partition by ID, CODE) as rowNum
   from table1;

   create table temp2 as
   select a.ID, a.CODE, a.RESULT, a.RESULT2, a.RESULT3
   from temp a
   inner join (select ID, CODE, max(rowNum) as maxRowNum
               from temp
               group by ID, CODE) b
     on a.ID=b.ID and a.CODE=b.CODE
   where (a.rowNum=1 and a.RESULT='A') or (a.rowNum=b.maxRowNum and a.RESULT NE 'A');
quit;

我看到有两个问题。

1)每个BY组中第一个或最后一个行完全依赖于SAS中table1中的行顺序,我们不按任何顺序排序。我不认为在转换为配置单元查询时会保留行顺序。

2)SAS代码占用每个BY GROUP中的第一行或最后一行,而不是两者。我认为我的HIVE查询占用了两者,导致行数超出了我想要的数量。

对于如何改进我的查询的任何建议或见解表示赞赏。甚至可以在HIVE中复制这个SAS代码吗?

2 个答案:

答案 0 :(得分:0)

关于第1点)BY组处理要求输入数据在BY变量上进行排序或索引,因此尽管代码不包含排序,但源数据按顺序处理。如果输入数据未编入索引/排序,SAS将抛出错误。 对此,可能的差异在于具有相同BY变量值的行,特别是如果RESULT不同。 在SAS中,我会按ID,CODE,RESULT对数据进行预排序,然后使用BY ID CODE,以免受行顺序的影响。

关于2)在SAS中,FIRST和LAST都是正确的。由于您在RESULT上的第一个和最后一个条件不同,我想这不是差异的来源。

我猜你可以添加另一个字段

row_number() over (partition by ID, CODE desc) as rowNumDesc

检测rowNumDesc = 1的最后一行(以便跳过连接)。

  

编辑:

我认为上面的两个程序都包括随机选择具有相同ID和CODE变量值的组的行,特别是具有相同的RESULT值。但是你应该从两者获得相同数量的行。如果没有,只需调试它。

然而,SAS代码/存储中的随机方面基于行的物理顺序,而组内的ROW_NUMBERs随机性将受到引擎中函数实现的影响。

答案 1 :(得分:0)

SAS代码有一个by语句(BY ID, CODE;),它告诉SAS set数据集在这些级别排序。因此,不是first.last.的随机选择。

尽管如此,我们可以使用first_valuelast_value窗口函数在HIVE中复制此内容。

FIRST.CODE应该复制到

first_value(code) over (partition by code)fcode

同样,LAST.CODE将是

last_value(code) over (partition by code)lcode

获得fcodelcode列后,请使用result列条件的语句。像,

case when (code=fcode and result='A') or (code=lcode and result<>'A')
then 1 else 0 end as op_flag

然后使用where op_flag = 1

获取表格

<强>样品

select id, code, result from (
select *,
first_value(code) over (partition by code)fcode,
last_value(code) over (partition by code)lcode
from footab) f
where (code=fcode and result='A') or (code=lcode and result<>'A')