背景
Hive SQL 代码的可读性一直是个问题哈,因为业务比较复杂,一般情况下写出来的代码也会很冗长,存在重复的逻辑,本篇通过一个工作过程中的示例来优化一下重复逻辑的问题,希望能够写出可读性更好的代码。
重复代码及问题
通过股票代码来判断所属市场,代码片段如下:
.....
CASE
WHEN substr( a.symbol, 1, 3 ) = '000' THEN
'深圳主板'
WHEN substr( a.symbol, 1, 3 ) = '001' THEN
'深圳主板'
WHEN substr( a.symbol, 1, 3 ) = '002' THEN
'中小企业板'
WHEN substr( a.symbol, 1, 3 ) = '003' THEN
'中小企业板'
WHEN substr( a.symbol, 1, 3 ) = '004' THEN
'中小企业板'
WHEN substr( a.symbol, 1, 3 ) = '688' THEN
'科创板'
WHEN substr( a.symbol, 1, 2 ) = '30' THEN
'创业板'
WHEN substr( a.symbol, 1, 2 ) = '60' THEN
'上海主板'
WHEN substr( a.symbol, 1, 1 ) IN ( '4', '8' ) THEN
'三板'
END AS mar_plate
.....
重复代码带来最大的问题就是可维护性,如果上面的代码在多个地方拷贝过,当逻辑需要修改时,要同时修改多处,如果有一处遗漏,就会出现 bug,排查起问题来是非常困难的,把自己坑死~
解决方案
自定义函数
重复的逻辑最先想到的是通过自定义函数来解决这个问题,此时就可以考虑使用用户自定义函数(UDF:user-defined function)
根据用户自定义函数类别分为以下三种:
UDF(User-Defined-Function)一进一出
UDAF(User-Defined Aggregation Function)聚集函数,多进一出,类似于:count/max/min
UDTF(User-Defined Table-Generating Functions)一进多出,如 lateral view explore()
自定义函数编程步骤:
- 第一步:创建 Maven Java 工程,导入 jar 包
- 第二步:继承
org.apache.hadoop.hive.ql.UDF
,并重载evaluate
方法 - 第三步:将项目打包,并上传到 Hive 的 lib 目录下
- 第四步:添加上传后的 jar 包
- 第五步:设置函数与自定义函数关联
但是像我们遇到的问题,并不是真正需要 UDF,而且 UDF 有更新维护也挺麻烦的,我们只是需要把一些繁琐、结构简单的逻辑封装起来以便重复在多个地方使用。
宏
宏可以看做是一个简短的函数,或者是对一个表达式取别名,同时可以将这个表达式中的一些值作为变量调用时传入,比较适合于需要用到很多次的表达式操作进行封装,然后取个简短点的别名来调用,省去了定义函数的复杂步骤哈。
创建一个宏,通过股票代码来判断所属市场
DROP TEMPORARY MACRO
IF
EXISTS getMarPlate;
CREATE TEMPORARY MACRO getMarPlate ( symbol string )
CASE
WHEN substr( symbol, 1, 3 ) = '000' THEN
'深圳主板'
WHEN substr( symbol, 1, 3 ) = '001' THEN
'深圳主板'
WHEN substr( symbol, 1, 3 ) = '002' THEN
'中小企业板'
WHEN substr( symbol, 1, 3 ) = '003' THEN
'中小企业板'
WHEN substr( symbol, 1, 3 ) = '004' THEN
'中小企业板'
WHEN substr( symbol, 1, 3 ) = '688' THEN
'科创板'
WHEN substr( symbol, 1, 2 ) = '30' THEN
'创业板'
WHEN substr( symbol, 1, 2 ) = '60' THEN
'上海主板'
WHEN substr( symbol, 1, 1 ) IN ( '4', '8' ) THEN
'三板'
END
前面的 SQL 就可以简化成下面的样子
......
getMarPlate(a.symbol) AS mar_plate
......
使用宏对这段逻辑进行提炼,起到优化开发效率、提升程序可读性的效果。
工作中常用的宏的场景:有关空值的处理,时间处理,数值计算,只要发现有类似的逻辑被反复调用,就可以考虑这种方式。
如果觉得还有帮助的话,你的关注和转发是对我最大的支持,O(∩_∩)O: