hive udf、udaf、udtf

一、UDF:用戶定義(普通)函數,只對單行數值產生做用;

實現方法:java

1. 繼承UDF類
2. 重寫evaluate方法apache

/**
     * @function 自定義UDF統計最小值
     * @author John
     *
     */
    public class Min extends UDF {

        public Double evaluate(Double a, Double b) {

            if (a == null)
                a = 0.0;
            if (b == null)
                b = 0.0;
            if (a >= b) {
                return b;
            } else {
                return a;
            }
        }
    }

二、UDAF:User- Defined Aggregation Funcation;用戶定義聚合函數,可對多行數據產生做用;等同與SQL中經常使用的SUM(),AVG(),也是聚合函數;

實現方法: 
一、用戶的UDAF必須繼承了org.apache.hadoop.hive.ql.exec.UDAF;
二、用戶的UDAF必須包含至少一個實現了org.apache.hadoop.hive.ql.exec的靜態類,諸如實現了 UDAFEvaluator
三、一個計算函數必須實現的5個方法的具體含義以下:
init():主要是負責初始化計算函數而且重設其內部狀態,通常就是重設其內部字段。通常在靜態類中定義一個內部字段來存放最終的結果。
iterate():每一次對一個新值進行彙集計算時候都會調用該方法,計算函數會根據彙集計算結果更新內部狀態。當輸 入值合法或者正確計算了,則       就返回true。
terminatePartial():Hive須要部分彙集結果的時候會調用該方法,必需要返回一個封裝了彙集計算當前狀態的對象。
merge():Hive進行合併一個部分彙集和另外一個部分彙集的時候會調用該方法。
terminate():Hive最終彙集結果的時候就會調用該方法。計算函數須要把狀態做爲一個值返回給用戶。
四、部分彙集結果的數據類型和最終結果的數據類型能夠不一樣。  數組

package hive.udaf;
 
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
 
public class Avg extends UDAF {
    public static class AvgState {
        private long mCount;
        private double mSum;
 
    }
 
    public static class AvgEvaluator implements UDAFEvaluator {
        AvgState state;
 
        public AvgEvaluator() {
            super();
            state = new AvgState();
            init();
        }
 
        /**
         * init函數相似於構造函數,用於UDAF的初始化
         */
        public void init() {
            state.mSum = 0;
            state.mCount = 0;
        }
 
        /**
         * iterate接收傳入的參數,並進行內部的輪轉。其返回類型爲boolean * * @param o * @return
         */
 
        public boolean iterate(Double o) {
            if (o != null) {
                state.mSum += o;
                state.mCount++;
            }
            return true;
        }
 
        /**
         * terminatePartial無參數,其爲iterate函數遍歷結束後,返回輪轉數據, * terminatePartial相似於hadoop的Combiner * * @return
         */
 
        public AvgState terminatePartial() {
            // combiner
            return state.mCount == 0 ? null : state;
        }
 
        /**
         * merge接收terminatePartial的返回結果,進行數據merge操做,其返回類型爲boolean * * @param o * @return
         */
 
        public boolean merge(AvgState avgState) {
            if (avgState != null) {
                state.mCount += avgState.mCount;
                state.mSum += avgState.mSum;
            }
            return true;
        }
 
        /**
         * terminate返回最終的彙集函數結果 * * @return
         */
        public Double terminate() {
            return state.mCount == 0 ? null : Double.valueOf(state.mSum / state.mCount);
        }
    }
}

三、UDTF:User-Defined Table-Generating Functions,用戶定義表生成函數,用來解決輸入一行輸出多行;

實現方法:ide

1. 繼承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF
2.initialize():UDTF首先會調用initialize方法,此方法返回UDTF的返回行的信息(返回個數,類型)
3.process:初始化完成後,會調用process方法,真正的處理過程在process函數中,在process中,每一次forward() 調用產生一行;若是產生多列      能夠將多個列的值放在一個數組中,而後將該數組傳入到forward()函數
4.最後close()方法調用,對須要清理的方法進行清理函數

import java.util.ArrayList;

 import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
 import org.apache.hadoop.hive.ql.metadata.HiveException;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
 import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
//切分」key:value;key:value;」這種字符串,返回結果爲key, value兩個字段
 public class ExplodeMap extends GenericUDTF{

     @Override
     public void close() throws HiveException {
         // TODO Auto-generated method stub    
     }

     @Override
     public StructObjectInspector initialize(ObjectInspector[] args)
             throws UDFArgumentException {
         if (args.length != 1) {
             throw new UDFArgumentLengthException("ExplodeMap takes only one argument");
         }
         if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
             throw new UDFArgumentException("ExplodeMap takes string as a parameter");
         }

         ArrayList<String> fieldNames = new ArrayList<String>();
         ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
         fieldNames.add("col1");
         fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
         fieldNames.add("col2");
         fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

         return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs);
     }

     @Override
     public void process(Object[] args) throws HiveException {
         String input = args[0].toString();
         String[] test = input.split(";");
         for(int i=0; i<test.length; i++) {
             try {
                 String[] result = test[i].split(":");
                 forward(result);
             } catch (Exception e) {
                 continue;
             }
         }
     }
 }

UDTF有兩種使用方法,一種直接放到select後面,一種和lateral view一塊兒使用oop

1:直接select中使用lua

select explode_map(properties) as (col1,col2) from src;

不能夠添加其餘字段使用spa

select a, explode_map(properties) as (col1,col2) from src

不能夠嵌套調用code

select explode_map(explode_map(properties)) from src

不能夠和group by/cluster by/distribute by/sort by一塊兒使用對象

select explode_map(properties) as (col1,col2) from src group by col1, col2

2:和lateral view一塊兒使用

select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable as col1, col2;
相關文章
相關標籤/搜索