数仓ETL(shell+sql)按天、周、月、季度汇总统计代码开发模板

目录

0 前言

1 shell中date用法小结

1.1基本语法

1.2 date 显示当前时间

1.3 date 显示非当前时间

2 按天统计

3 按周统计

4 按月统计

5 按季度统计

6 小结



0 前言

数仓ETL统计的时候,我们往往需要对数据进行按天、周、月、季度等几个时间维度进行批量统计。一般的开发模式都为shell中套sql的形式,这样我们可以根据定时任务跑shell脚本,同时利用shell编写一些函数来代替SQL中的存储过程。本文中的天、周、月、季度的时间维度,也是利用shell中的时间函数进行计算,这样降低了sql开发的难度,代码可维护性更高。

shell中时间的获取常常采用date -d 或date --date来获取

1 shell中date用法小结

1.1基本语法

1)基本语法

date [OPTION]... [+FORMAT]

2)选项说明

表1-20

选项

功能

-d<时间字符串>

显示指定的“时间字符串”表示的时间,而非当前时间

-s<日期时间>

设置系统日期时间

3)参数说明

表1-21

参数

功能

<+日期时间格式>

指定显示时使用的日期时间格式

1.2 date 显示当前时间

1)基本语法

(1)date                                                        (功能描述:显示当前时间)

(2)date +%Y                                               (功能描述:显示当前年份)

(3)date +%m                                               (功能描述:显示当前月份)

(4)date +%d                                                (功能描述:显示当前是哪一天)

(5)date "+%Y-%m-%d %H:%M:%S"            (功能描述:显示年月日时分秒)

2)案例实操

(1)显示当前时间信息

[root@bigdata-1 ~]# date

2020年 10月 26日 星期一 13:40:45 CST

(2)显示当前时间年月日

[root@bigdata-1 ~]# date +%Y%m%d

20201026

(3)显示当前时间年月日时分秒

[root@bigdata-1 ~]# date "+%Y-%m-%d %H:%M:%S"

2020-10-26 13:42:15

1.3 date 显示非当前时间

1)基本语法

(1)date -d '1 days ago'                     (功能描述:显示前一天时间)

(2)date -d '-1 days ago'                   (功能描述:显示明天时间)

2)案例实操

(1)显示前一天

[root@bigdata-1 ~]# date -d '1 days ago'

2020年 10月 25日 星期日 13:42:45 CST
[root@bigdata-1 ~]# date -d '-1 days'

2020年 10月 25日 星期日 13:43:25 CST

[root@bigdata-1 ~]# date -d 'last day'

2020年 10月 25日 星期日 13:43:51 CST


(2)显示明天时间

[root@bigdata-1 ~]# date -d '1 days'

2020年 10月 27日 星期二 13:44:53 CST

[root@bigdata-1 ~]# date -d '-1 days ago'

2020年 10月 27日 星期二 13:44:28 CST

[root@bigdata-1 ~]# date -d 'next day'

2020年 10月 27日 星期二 13:47:37 CST

(3)指定时间显示

[root@bigdata-1 ~]# date -d '2020-10-26 3 months ago'

2020年 07月 26日 星期日 00:00:00 CST

1.4 date 设置系统时间

1)基本语法

       date -s 字符串时间

2)案例实操

       (1)设置系统当前时间

[root@bigdata-1 ~]# date -s "2020-10-26 13:52:18" 

2 按天统计

#!/bin/bash

#1获取时间
lastday=`date --date '-1days' +%F` #获得昨天的日期(今天算昨天的)
if [ "$1" != "" ];then
    lastday=$1
fi;
#2定义变量
hive='/usr/idp/current/hive-client/bin/hive';
APP=phmdwdb
input_table="${APP}.输入表名";
output_table="${APP}.输出表名";

#3写SQL
sql="
insert overwrite table ${output_table}
PARTITION (compute_day='${lastday}')
select
     ,xxx
     ,xxx
     ,xxx
from ${input_table}
where compute_day='${lastday}' 
...........
...........  
;
";

#执行SQL

${hive} -e "${sql}" >>/tmp/${output_table}.log  2>&1 ;

3 按周统计

#!/bin/bash

#按周统计的表依赖于按天统计的表,因此输入的表为按天统计的表
#1获取时间,每周周一开始算上周的任务
today=`date +%F` #获得当前的日期
start_week=`date -d "${today} -7 days" +%F` #获取上周的周一日期
end_week=`date -d "${today} -1 days" +%F` #获取上周的周末日期
day=`date -d "${today}" +%w` #获取if条件中要匹配的日期
compute_week=`date -d "${start_week}" +%V` #%V:以周一为每周的第一天。%U:以以周日为每星期第一天
if [ "$1" != "" ];then
    today=$1
fi;

#2定义变量
hive='/usr/idp/current/hive-client/bin/hive';
APP=phmdwdb
input_table="${APP}.输入表名";
output_table="${APP}.输出表名";

#3写SQL
sql="
insert overwrite table ${output_table}
PARTITION (compute_week='${compute_week}')
select
     ,xxx
     ,xxx
     ,xxx
from ${input_table}
where compute_day>='${start_week}' and compute_day<'${today}' --注意按周分析的依赖于按天统计的表,所以用compute_day
...........
...........  
;
";

#执行SQL

if [ ${day} == '1' ];then

   ${hive} -e "${sql}"   >>/tmp/$log_dir.log  2>&1 ;
else
   echo '只有在周一计算上一周的统计值';
fi

4 按月统计

#!/bin/bash

#按月统计的表依赖于按天统计的表,因此输入的表为按天统计的表
#1获取时间,每月初开始算上月的任务
today=`date +%Y-%m-%d` #获得当前的日期
start_date=`date -d "${today} -1 days " +%Y-%m-01` #获得上个月月初的时间
end_date=`date -d"${today} last day" +%Y-%m-%d` #上个月最后一天
day=`date -d "${today}"+%d`; #获取当前需要匹配的时间.(只有月初的时候才会计算,月初时获取天值为01)
compute_month=`date -d ${start_date} +%Y-%m`; #获取静态分区的指定健值。计算的是上个月。

if [ "$1" != "" ];then
    today=$1
fi;

#2定义变量
hive='/usr/idp/current/hive-client/bin/hive';
APP=phmdwdb
input_table="${APP}.输入表名";
output_table="${APP}.输出表名";

#3写SQL
sql="
insert overwrite table ${output_table}
PARTITION (compute_month='${compute_month}')
select
     ,xxx
     ,xxx
     ,xxx
from ${input_table}
where compute_day>='${start_date}' and compute_day<'${today}' --注意按月分析的依赖于按天统计的表,所以用compute_day
...........
...........  
;
";

#执行SQL.月的时候匹配的是01

if [ ${day} == '01' ];then

   ${hive} -e "${sql}"   >>/tmp/$log_dir.log  2>&1 ;
else
   echo '只有在月初计算上一月的统计值';
fi

5 按季度统计

 注意:该脚本统计时候使用了shell的除法运算,shell的除法采用bc计算器进行完成,其中scale是小数位数,注意/两边是都有空格的。在shell计算加减乘除的时候,如果是整数运算一般采用$((a+b))或$[a+b],如果是小数运算一般用bc计算器进行运算,scale控制器小数位数。

#!/bin/bash

#按季度统计的表依赖于按月统计的表,因此输入的表为按月统计的表
#1获取时间,每季度初开始算上季度的任务
today=`date +%F` #获取当前的日期	 
current_month=`date -d "${today}" +%Y-%m` #获取当前的月份
start_month=`date -d "${today} 3 month ago" +%Y-%m` #获取季度开始的月份
end_month=`date -d "${today} -1 month" +%Y-%m` #获取季度结束的月份
match=`date -d "${today}" +%m` #获取条件需要匹配的值
temp=`date -d ${start_quarter}_01 +%m` #获取上一季度开始的月份数字,作为中间结果值
compute_quarter=`echo "scale=0; (${temp}-1) / 3 + 1" | bc` # 计算静态分区的健值,季度值。按月份求季度的算法。

if [ "$1" != "" ];then
    today=$1
fi;

#2定义变量
hive='/usr/idp/current/hive-client/bin/hive';
APP=phmdwdb
input_table="${APP}.输入表名";
output_table="${APP}.输出表名";

#3写SQL
sql="
insert overwrite table ${output_table}
PARTITION (compute_quarter='${compute_quarter}')
select
     ,xxx
     ,xxx
     ,xxx
from ${input_table}
where compute_month>='${start_month}' and compute_month<'${current_month}' --注意按季度分析的依赖于按月统计的表,所以用compute_month
...........
...........  
;
";

#执行SQL.季度的时候匹配的是01,04,07,10.每过一季度统计一次

if [ ${match} == '01' ]; then 
${hive} -e "set mapred.job.name=统计第四季度;${sql}"  >>/tmp/$log_dir.log  2>&1;
elif [ ${match} == '04' ]; then
${hive} -e "set mapred.job.name=统计第一季度;${sql}"  >>/tmp/$log_dir.log  2>&1;
elif [ ${match} == '07' ]; then
${hive} -e "set mapred.job.name=统计第二季度;${sql}"  >>/tmp/$log_dir.log  2>&1;
elif [ ${match} == '10' ]; then
${hive} -e "set mapred.job.name=统计第三季度;${sql}"  >>/tmp/$log_dir.log  2>&1;
else
echo '只有等到季度初的时候才进行统计';
fi 

6 小结

本文几个代码开发模板也是实际ETL统计中经常用到的,文章对数仓常见的几个时间维度统计代码进行了总结,将其抽象成模板以供读者参考和使用,

猜你喜欢

转载自blog.csdn.net/godlovedaniel/article/details/109264067