【问题标题】:Summing values of Hive array typesHive 数组类型的求和值
【发布时间】:2012-09-05 01:07:58
【问题描述】:

Hive 有一个非常棒的 Array 类型,它在理论上非常有用,但是在实践中,我发现关于如何使用它进行任何类型的操作的信息非常少。 我们将一系列数字存储在数组类型的列中,并且需要在查询中对它们求和,最好是从第 n 个元素到第 m 个元素。是否可以使用标准 HiveQL 或是否需要 UDF 或客户映射器/缩减器?

注意:我们在 EMR 环境中使用 Hive 0.8.1。

【问题讨论】:

    标签: arrays hadoop aggregate hive aggregation


    【解决方案1】:

    为此,我会写一个简单的UDF。您需要在构建路径中包含 hive-exec
    例如Maven:

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

    一个简单的原始实现如下所示:

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

    接下来,构建一个 jar 并将其加载到 Hive shell 中:

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

    现在您可以使用它来计算您拥有的数组的总和。

    例如:

    假设您有一个输入文件,其中包含制表符分隔的列:

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

    将其加载到 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';
    

    然后执行一些查询:

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

    在 m,n 范围内求和,其中 m=1, n=3

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

    或者

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

    【讨论】:

      【解决方案2】:

      上面的答案解释得很好。我发布了一个非常简单的 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;
              }
          }
      

      同时发布表创建和其他查询。

      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;
      

      我的输入文件看起来像

      1,3~5~8~5~7~9
      2,93~5~8~5~7~29
      3,3~95~8~5~27~9
      4,3~5~58~15~7~9
      5,3~25~8~55~7~49
      6,3~25~8~15~7~19
      7,3~55~78~5~7~9

      我已经创建了我的 UDF 的 jar,我使用以下命令将 jar 添加到 hive

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

      然后我创建如图所示的临时函数

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

      执行如下示例查询,

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

      这应该可以解决最基本的需求。如果这不是问题陈述,请回复,以便我再次为您提供帮助。

      【讨论】:

        猜你喜欢
        • 2019-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-28
        • 1970-01-01
        • 2020-05-25
        相关资源
        最近更新 更多