我有一个包含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代码吗?
答案 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_value
和last_value
窗口函数在HIVE中复制此内容。
FIRST.CODE
应该复制到
first_value(code) over (partition by code)fcode
同样,LAST.CODE
将是
last_value(code) over (partition by code)lcode
获得fcode
和lcode
列后,请使用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')