2015-08-12 3 views
0

У меня есть таблица с 3 столбцами:HIVE эквивалент FIRST и LAST

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 и код, а затем записывая данные в набор данных, если выполняются определенные условия. Я хочу написать запрос на улей, чтобы воспроизвести это. Это то, что у меня есть:

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, полностью зависит от порядка строк в таблице 1 в SAS, мы ничего не заказываем. Я не думаю, что порядок строк сохраняется при переводе на запрос куста.

2) Код SAS занимает первую строку в каждой группе BY GROUP или последней, а не в обеих. Я думаю, что мой запрос HIVE принимает оба, в результате чего больше строк, чем я хочу.

Любые предложения или понимание того, как улучшить мой запрос, оценены. Возможно ли повторить этот код SAS в HIVE?

+0

существует 'FIRST_VALUE()' и 'last_value()' функция в улье https: // cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics – gobrewers14

ответ

0

Что касается точки 1) обработка группы BY требует, чтобы входные данные были отсортированы или индексированы по переменным BY, поэтому, если код не содержит порядка, исходные данные обрабатываются по порядку. Если входные данные не были проиндексированы/отсортированы, SAS выдаст ошибку. Исходя из этого, возможные различия относятся к строкам с одинаковыми значениями переменных BY, особенно если RESULT отличается. В SAS я бы предварительно сортировал данные по ID, CODE, RESULT, а затем использовал BY ID CODE, чтобы не влиять на порядок строк.

Относительно 2) FIRST и LAST могут быть как в SAS. Поскольку ваше условие для первого и последнего в РЕЗУЛЬТАТЕ отличается, я полагаю, что это не источник различий.

Я думаю, вы могли бы добавить еще одно поле

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

обнаружить последнюю строку с rowNumDesc = 1 (так что вы пропустите присоединиться).

РЕДАКТИРОВАТЬ:

Я считаю, что две программы выше оба включают случайный выбор строк для групп с одинаковыми значениями ID и код переменных, особенно с теми же значениями РЕЗУЛЬТАТ. Но вы должны получить такое же количество строк из обоих. Если нет, просто отлаживайте его.

Однако случайный аспект в коде/хранилище SAS основан на физическом порядке строк, тогда как случайная случайность ROW_NUMBERS внутри группы будет зависеть от реализации функции в движке.

+0

Так как код SAS находится в OP, можно ли его реплицировать в куст или sql? Потому что, если есть связь, я думаю, что SAS выберет буквальную «последнюю» строку в группе, тогда как в hive/sql она, вероятно, будет выбрана случайным образом? @vasja – Danzo

0

Код SAS имеет оператор by (BY ID, CODE;), который сообщает SAS, что набор данных set сортируется на этих уровнях. Итак, не случайный выбор для first. и last..

При этом мы можем воспроизвести это в HIVE с помощью оконных функций first_value и last_value.

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') 
Смежные вопросы