2012-09-12 14 views
6

Hive hat diesen ziemlich schönen Array-Typ, der in der Theorie sehr nützlich ist, aber wenn es um die Praxis geht, fand ich sehr wenig Informationen darüber, wie man damit operiert. Wir speichern eine Reihe von Zahlen in einer Array-Typ-Spalte und müssen sie in einer Abfrage SUMMEN, vorzugsweise von n-ten bis m-ten Element. Ist es möglich mit Standard HiveQL oder benötigt es einen UDF oder Kunden Mapper/Reducer?Summenwerte von Hive-Array-Typen

Hinweis: Wir verwenden Hive 0.8.1 in EMR-Umgebung.

Antwort

9

Ich würde eine einfache 10 für diesen Zweck schreiben. Sie müssen hive-exec in Ihrem Build-Pfad haben.
zB bei Maven:

<dependency> 
    <groupId>org.apache.hive</groupId> 
    <artifactId>hive-exec</artifactId> 
    <version>0.8.1</version> 
</dependency> 

Eine einfache rohe Umsetzung würde wie folgt aussehen:

package com.myexample; 

import java.util.ArrayList; 
import java.util.List; 

import org.apache.hadoop.hive.ql.exec.UDF; 
import org.apache.hadoop.io.IntWritable; 

public class SubArraySum extends UDF { 

    public IntWritable evaluate(ArrayList<Integer> list, 
     IntWritable from, IntWritable to) { 
     IntWritable result = new IntWritable(-1); 
     if (list == null || list.size() < 1) { 
      return result; 
     } 

     int m = from.get(); 
     int n = to.get(); 

     //m: inclusive, n:exclusive 
     List<Integer> subList = list.subList(m, n); 

     int sum = 0; 
     for (Integer i : subList) { 
      sum += i; 
     } 
     result.set(sum); 
     return result; 
    } 
} 

Als nächstes bauen ein Glas und laden Sie es in Hive-Shell:

hive> add jar /home/user/jar/myjar.jar; 
hive> create temporary function subarraysum as 'com.myexample.SubArraySum'; 

Jetzt können Sie es verwenden, um die Summe des Array zu berechnen, das Sie haben.

ZB:

Nehmen wir an, dass Sie eine Eingabedatei mit Tabula getrennt haben Spalten in es:

1 0,1,2,3,4 
2 5,6,7,8,9 

laden Sie es in Mytable:

hive> create external table mytable (
    id int, 
    nums array<int> 
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' 
COLLECTION ITEMS TERMINATED BY ',' 
STORED AS TEXTFILE 
LOCATION '/user/hadoopuser/hive/input'; 

einige Abfragen ausführen, dann:

hive> select * from mytable; 
1 [0,1,2,3,4] 
2 [5,6,7,8,9] 

Summe es sich in Reichweite m, n, wobei m = 1, n = 3

hive> select subarraysum(nums, 1,3) from mytable; 
3 
13 

Oder

hive> select sum(subarraysum(nums, 1,3)) from mytable; 
16 
1

Die Antwort oben recht gut erklärt. Ich poste eine sehr einfache Implementierung der UDF.

package com.ak.hive.udf.test; 

import java.util.ArrayList; 

import org.apache.hadoop.hive.ql.exec.UDF; 

    public final class ArraySumUDF extends UDF { 
     public int evaluate(ArrayList<Integer>arrayOfIntegers,int startIndex,int endIndex) { 
      // add code to handle all index problem 
        int sum=0; 
      int count=startIndex-1; 
      for(;count<endIndex;count++){ 
       sum+=arrayOfIntegers.get(count); 
      } 
      return sum; 
     } 
    } 

Auch Buchung der Tabellenerstellung und andere Abfragen.

create table table1 (col1 int,col2 array<int>)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY '~' STORED AS TEXTFILE; 

load data local inpath '/home/ak/Desktop/hivedata' into table table1; 

würde meine Eingabedatei wie

aussehen

1,3 ~ 5 ~ 8 ~ 5 ~ 7 ~ 9
2,93 ~ 5 ~ 8 ~ 5 ~ 7 ~ 29
3,3 [ ] [0034] 5,3-5-58-15-7-9-012- 5,3-25-8-55-7-49
6,3 ~ 25 ~ 8 ~ 15 ~ 7 ~ 19
7,3 ~ 55 ~ 78 ~ 5 ~ 7 ~ 9

Ich habe ein Glas meiner UDF erstellt, ich füge th hinzu e Glas als

create temporary function getSum as 'com.ak.hive.udf.test.ArraySumUDF'; 

eine Beispielabfrage, wie unten angezeigt werden mit dem folgenden Befehl

add jar file:///home/ak/Desktop/array.jar; 

Dann erstelle ich temporäre Funktion liedern,

select col1,getSum(col2,1,3) from table1; 

Dies sollte die sehr grundlegende Notwendigkeit lösen . Sollte dies nicht der Fall sein, antworten Sie bitte zurück, damit ich Ihnen wieder helfen kann.

Verwandte Themen