Hive 獲取陣列最後一個元素

語言: CN / TW / HK

引言:

通過split分割當前欄位獲取陣列,並得到最後一個索引的元素,通過hive怎麼實現,下面通過不同方法一一驗證可行性。

欄位樣式 shopList  : productA,productB,productC 

表名 shopTable :  shopListTable

 

一.split + size 獲取 - 失敗

 hive -e "
 select split(shopList,',')[size(split(shopList,','))-1]
 from shopTable;
 "
FAILED: SemanticException 2:25 Non-constant expressions for array indexes not supported. Error encountered near token '1'

遇到這個問題第一反應就是split轉化為陣列,再通過陣列size-1獲取最後一位,但是 array 的索引位置不允許非常數的表示式,所以失敗。

 

二.split + size + cast 獲取 - 失敗

hive -e "
select array[index] as product
from
( select split(shopList,',') array, cast((size(split(shopList,',')) - 1) as int) index from shopTable) tmp
";
FAILED: SemanticException 2:12 Non-constant expressions for array indexes not supported. Error encountered near token 'index'

和上面的問題類似,有點坑,繼續嘗試。

 

三. regexp_extract - 能跑但效果不對

hive -e "
select regexp_extract(shopList,'(\,[^\,]+)',1) 
from shopTable
";

split 和 regexp_extract 作用類似,但是這裡正則表示式使用起來有問題,還是暫不考慮。

 

四. reverse + split + reverse - 成功

hive -e "
select reverse(split(reverse(shopList), ',')[1]) 
from shopTable";

看網上大神這麼操作的,實測沒有問題,但是效能和資源消耗都比較嚴重。

 

五.自定義UDF - 成功 (推薦👍)

截止目前上面四種方法只有 reverse 一種可以實現但是效率還是個問題,所以出大招直接自己寫函式好了。

java : 

package com.hive.udf;

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

import java.util.List;

/**
 * @title: SplitString
 * @Date: 2021-01-21 14:21
 * @Version 1.0
 */
public final class SplitString extends UDF {
    public Text evaluate(final Text s) {
        if (s == null) { return null; }
        String[] arr = s.toString().split(",");
        if ( arr.length == 0) { return null; }
        return new Text(arr[arr.length - 1]);
    }
}

sh :

hive -e "
add jar ~/your-class-1.0-SNAPSHOT.jar;
create temporary function my_split as 'com.hive.udf.SplitString';
select my_split(shopList) from shopTable group by my_split(shopList);
"

將java程式碼打包,並上傳至sh指令碼對應位置即可,通過自定義的方法實現 split + index 功能,這裡不侷限於倒數第一位,倒數第幾位都可以,實測效能優於 reverse, 值得擁有!

除了UDF(一進一出)之外,還有 UDAF (多進一出)和 UDTF(一進多出)等形式,有興趣也可以自己實現~