2013-08-09 4 views
2

HiveQL rank()를 이해할 수 없습니다. WWW에서 rank UDF를 구현 한 예가 두 개 발견되었습니다 (예 : Edward's nice example). 함수를로드하고 액세스 할 수는 있지만 원하는대로 할 수는 없습니다.HiveQL 및 rank()

CLI를 프로세스에 UDF 넣기 :이 CSV에서

create table purchases (
    SalesRepId String, 
    PurchaseOrderId INT, 
    Amount INT 
) 
ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY ',' 
    LINES TERMINATED BY '\n'; 

데이터로드 :

Jana,1,100 
Nadia,2,200 
Nadia,3,600 
Daniel,4,80 
Jana,5,120 
William,6,170 
Daniel,7,140 

함께

$ javac -classpath /home/hadoop/hadoop/hadoop-core-1.0.4.jar:/home/hadoop/hive/lib/hive-exec-0.10.0.jar com/m6d/hiveudf/Rank2.java 
$ jar -cvf Rank2.jar com/m6d/hiveudf/Rank2.class 
hive> ADD JAR /home/hadoop/MyDemo/Rank2.jar; 
hive> CREATE TEMPORARY FUNCTION Rank2 AS 'com.m6d.hiveudf.Rank2'; 

테이블을 만들고 여기에 대한 상세한 예는 CLI의 다음과 같습니다.

LOAD DATA 
    LOCAL INPATH '/home/hadoop/MyDemo/purchases.csv' 
    INTO TABLE purchases; 

지금은 내 최고 판매 담당자를 볼 수 있습니다

select SalesRepId,sum(amount) as volume 
from purchases 
group by SalesRepId 
ORDER BY volume DESC; 

나디아 물건의 $ (800) 판매하고, 다니엘과 야나는 모두 $ 220 판매, 그리고 윌리엄 지금 $ (170)

SalesRep Amount 
-------- ------ 
Nadia  800 
Daniel  220 
Jana  220 
William  170 

모든 I를 판매했다 하고 싶은 것은 그들에게 수에게 있습니다 : 나디아는 ​​# 1, 다니엘과 야나는 # 2 공동, 윌리엄은 # 4 (하지 # 3)이다 있습니다

select SalesRepId, V.volume,rank2(V.volume) 
from 
(select SalesRepId,sum(amount) as volume 
from purchases 
group by SalesRepId 
ORDER BY volume DESC) V; 

SalesRep Amount Rank 
-------- ------ ---- 
Nadia  800  1 
Daniel  220  2 
Jana  220  2 
William  170  4 

당신이 나를 도울 수 :들 내가 무엇을 얻을,하지만 난 원하지 무엇을 :

SalesRep Amount Rank 
-------- ------ ---- 
Nadia  800  1 
Daniel  220  1 
Jana  220  2 
William  170  1 

이 내가 원하는 것입니다,하지만 난 하이브 할 수없는 나를 위해 그것을 할 HiveQL을 수정하여 영업 담당자의 순위를 매기십시오.

JtheRocker에게 감사드립니다. 그의 변화는이 목록에 결과 : 나디아를 보여

SalesRep Amount Rank 
-------- ------ ---- 
William  170  1 
Daniel  220  2 
Jana  220  2 
Nadia  800  3 

약간의 수정과 같은 4 (3되지 않음) :

private row_number; 
@Override 
public Object evaluate(DeferredObject[] currentKey) throws HiveException { 
    row_number++; 
    if (!sameAsPreviousKey(currentKey)) { 
    this.counter = row_number; 
    copyToPreviousKey(currentKey); 
    } 
return new Long(this.counter); 
} 
+0

당신에게 어떤 도움의 내 대답인가? 응답하십시오. 이 사용 사례에 매우 관심이 있습니다. 감사! –

답변

6

, 당신은 사용할 수 있습니다

select SalesRepId, volume as amount , rank() over (order by V.volume desc) as rank from 
(select SalesRepId,sum(amount) as volume from purchases group by SalesRepId) V; 
+0

고마워요 libjack. 이 예제를 https://blogs.oracle.com/taylor22/entry/hive_0_11_may_15 –

+0

에있는 카테고리 내에서 정렬하도록 확장했습니다. 해당 양식에도 매우 유용합니다. 블로그에 멋진 글을 남깁니다. – libjack

1

당신은 당신이 함수를 직접 사용하는 가정, 아래와 같은 평가 기능이있는 경우 같은 volu를 발견하면 당신이 언급 한 가이드가 새 볼륨을 발견하면 카운터가 재설정되지 않도록

private long counter; 
@Override 
    public Object evaluate(DeferredObject[] currentKey) throws HiveException { 
    if (!sameAsPreviousKey(currentKey)) { 
     this.counter = 0; 
     copyToPreviousKey(currentKey); 
    } 

    return new Long(++this.counter); 
    } 

오히려 당신이 증가하지 않는, 다음에 변경 시도를 형성 새로운 볼륨을 발견 할 때만 증가합니다.

private long counter; 
@Override 
    public Object evaluate(DeferredObject[] currentKey) throws HiveException { 
    //when not same as previous key you rather increment 
    if (!sameAsPreviousKey(currentKey)) { 
     this.counter ++; 
     copyToPreviousKey(currentKey); 
    } 
    //else you keep the counter as it is 
    return new Long(++this.counter); 
} 

이 정보가 도움이되는지 알려주십시오. 하이브 0.11에 도입 된 Windowing and Analytics functions

+0

JtheRocker에게 감사의 말을 전합니다. 그의 변화로 인해 Oracle DENSE_RANK와 비슷한 순위가 매겨졌습니다.Oracle RANK와 유사한 방식으로이 Hive UDF를 평가하려면 위 수정을 참조하십시오. –

+0

나는 '1,2,2,4'라는 명령에주의를 기울이지 않았는데, 대답을 게시하고 이것을 1,2,2,3 대신하고 싶다고 생각했다. :) 저를 정정 해 주셔서 감사 드리며 원하는 솔루션을 찾는데 도움이되었음을 기쁘게 생각합니다. :) –