복붙노트

[HADOOP] HiveQL 및 rank ()

HADOOP

HiveQL 및 rank ()

나는 HiveQL rank ()를 이해할 수 없다. 에드워드 (Edward)의 훌륭한 예와 같이 WWW에서 순위 UDF를 몇 가지 구현 한 것을 발견했습니다. 함수를로드하고 액세스 할 수는 있지만 원하는대로 할 수는 없습니다. 다음은 상세한 예입니다.

CLI 프로세스에 UDF로드 :

$ 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'; 

표 만들기 :

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

이 CSV에서 데이터로드 :

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

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

이제 나디아는 ​​# 1, 나디아는 ​​# 2, 다니엘과 야나는 # 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      1
Jana        220      2
William     170      1

이것은 내가 원하는 것이지만, 하이브를 나를 위해 할 수는 없다.

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

판매원에게 순위를 매기는데 정확한 HiveQL을 도와 줄 수 있습니까?

JtheRocker에게 감사의 말을 전합니다. 그의 변화로이 목록이 나왔습니다.

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

Nadia가 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);
}

해결법

  1. ==============================

    1.Hive 0.11에 도입 된 창 및 분석 기능을 사용하면 다음을 사용할 수 있습니다.

    Hive 0.11에 도입 된 창 및 분석 기능을 사용하면 다음을 사용할 수 있습니다.

    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;
    
  2. ==============================

    2.아래의 평가 함수가있는 경우 함수를 사용하여 앞서 언급 한 지침을 직접 작성한다고 가정하면,

    아래의 평가 함수가있는 경우 함수를 사용하여 앞서 언급 한 지침을 직접 작성한다고 가정하면,

    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);
     }
    

    이게 도움이되는지 말해봐.

  3. from https://stackoverflow.com/questions/18156105/hiveql-and-rank by cc-by-sa and MIT license