最近遇到把sas代码翻译成hive代码中发现这样一个问题,在sas代码中总是有很多重复代码:从指标表中读取指标代码,如果指标代码在表中则执行此程序,不在则不执行。sas中有if和goto语句进行判断,但hive中并没有这样的语法。
以前用的方法是将ETL的表和指标表进行join,on的条件为1=1(因为指标表和ETL的表没有关联字段),再在where条件加上指标表输出的字段is not null的语句。
此方法存在的缺点有:
1.这种方法如果指标表输出结果只有一条,可以实现功能,但如果指标表输出的结果有多条,那join后必定会产生笛卡尔积,效率不高,还可能会出错数据错误
2.会出现很多重复的代码,代码不简洁
此现象我们可以结合shell脚本做优化
创建指标表
create table index_tb (
id int comment "主键ID",
index_id varchar(6) comment "指标代码",
type_id int comment "类型ID"
);
插入模拟数据
insert into index_tb values
(1, "a_2856", 1),
(2, "c_3876", 2),
(3, "d_2856", 1),
(4, "a_3859", 2),
(5, "f_3556", 2),
(6, "h_7856", 1),
(7, "b_2856", 1);
将判断是否执行指标代码的代码封装到一个脚本中is_execute.sh
#!/bin/bash
index_id=$1
type_id=$2
#echo ${index_id}
#echo ${type_id}
#将SQL语句执行结果赋值给变量flag
flag=`/opt/modules/hive-3.1.1/bin/hive -e "
--不打印字段名称
set hive.cli.print.header=false;
select id from db_window.index_tb where index_id='${index_id}' and type_id=${type_id} limit 1;
"`
#echo "flag is :"${flag}
#将flag变量的结果赋值给调用的变量
echo ${flag}
修改脚本文件的权限为可执行文件
chmod u+x is_execute.sh
编写执行脚本test.sh
#!/bin/bash
#将is_execute.sh脚本中flag变量的值赋值给is_execute变量
is_execute=`/opt/modules/hive-3.1.1/shell/is_execute.sh a_2856 2`
echo "is_execute is :" ${is_execute}
#判断脚本is_execute.sh脚本输出结果的长度是否等于0,等于0则不执行程序,否则执行程序
if [ ${#is_execute} = 0 ];then
echo "不执行程序"
else
echo "执行程序"
/opt/modules/hive-3.1.1/bin/hive -e "
select * from deal_tb limit 2;
"
fi
修改脚本文件的权限为可执行文件
chmod u+x test.sh
这样我们在执行代码中前只要调用is_execute.sh脚本将变量赋值给is_execute变量,再判断该变量长度是否等于0,等于0则不执行接下来的SQL代码,不等于0则执行
因为脚本中传入的两个参数a_2856 2不在表index_tb中,所以不执行后续的SQL语句
将参数改为a_2856 1,再运行test.sh脚本,会执行后续的SQL语句
因为执行后的结果不在一张截图,所以在is_execute.sh脚本中执行hive语句添加-S参数,日志不输出到控制台
#!/bin/bash
index_id=$1
type_id=$2
#echo ${index_id}
#echo ${type_id}
#将SQL语句执行结果赋值给变量flag
flag=`/opt/modules/hive-3.1.1/bin/hive -S -e "
set hive.cli.print.header=false;
select id from db_window.index_tb where index_id='${index_id}' and type_id=${type_id} limit 1;
"`
#echo "flag is :"${flag}
#将flag变量的结果赋值给调用的变量
echo ${flag}
#!/bin/bash
is_execute=`/opt/modules/hive-3.1.1/shell/is_execute.sh a_2856 1`
echo "is_execute is :" ${is_execute}
if [ ${#is_execute} = 0 ];then
echo "不执行程序"
else
echo "执行程序"
/opt/modules/hive-3.1.1/bin/hive -e "
select * from db_window.deal_tb limit 2;
"
fi