目录
0 基础函数
trunc()
last_day()
add_months()
current_date()/current_date
next_day
pmod()
to_date
year
month
hour
dayofweek
weekofyear
quarter
datediff
date_add
date_sub
add_months
months_between
date_format
1 关于月的计算
1.1上月末
1.2上月初
1.3本月初
1.4 本月末
2 关于周计算
2.1 本周一
2.2 本周末
2.3 上周一
2.4上周末
2.5 根据当前日期得出星期几
3 关于季度计算
3.1季度初方法一
3.2 季度初方法二
3.3 获取季度末的方法
4 关于年计算
4.1 年开始日期
4.2 年结束的日期
5 时间日期维度表生成
trunc(string date,string format) — 返回日期的最开始日期
目前格式支持:MM(月)YYYY(年)Hive3.0后支持Q表示季度
select trunc(current_date,'MM') --月初
select trunc(current_date,'YY') --年初
last_day(string date) — 返回该月最后一天的日期
select last_day(current_date());
add_months(string date,int months) — 返回months月之后的date,months可以是负数
select add_months(current_date(),1);
当前日期(天)
select current_date
next_day(string date,string dayOfWeek) — 返回date之后的下一个周的dayOfWeek的天
求当前日期的下周一时间
select next_day(current_date,'MO')
pmod(int a, int b)
pmod(double a, double b)
返回a除以b的余数的绝对值
select pmod(10,4)
语法:to_date(string timestamp)
返回值: 2.1.0版本前返回string,2.1.0版本后返回date
描述: 将一个字符串date按照"yyyy-MM-dd"格式转成日期值.
select to_date(current_timestamp)
语法:year(string date)
返回值:int
描述:提取日期中的年份部分
select year(current_timestamp)
语法:month(string date)
返回值: int
描述:提取日期中的月份部分
select month(current_timestamp)
语法:hour(string date)
返回值:int
描述:提取日期中的小时部分
select hour(current_timestamp)
获取当前日期的星期几。这里本周的第一天是周日,使用时候注意转换。Hive低版本没有该函数,Hive2.1版本之后才有,如果版本较低建议使用pmod方法获取当前日期的星期几,参考下文。
select dayofweek('2022-05-29 20:21:22')
语法:weekofyear(string date)
返回值:int
描述: 返回指定日期处于当年的第几周
select weekofyear('2022-05-29') as weekofyear;
获取当前日期所处的季度
select quarter('2022-05-29 20:21:22')
低版本没有该函数,可以用ceil(month(date) / 3)来代替
select CEIL(month('2022-05-29 20:21:22') / 3)
语法:datediff(string enddate, string startdate)
返回值: int
描述: 返回两指定日期之间的天数
select datediff('2022-05-30', '2022-05-15')
语法:date_add(date/timestamp/string startdate, tinyint/smallint/int days)
返回值: 2.1.0版本前返回string,2.1.0版本后返回date
描述:返回开始日期startdate增加天数days后的日期
select date_add('2022-05-15', 5);
语法: date_sub(date/timestamp/string startdate, tinyint/smallint/int days)
返回值: 2.1.0版本前返回string,2.1.0版本后返回date
描述: 返回开始日期startdate减少天数days后的日期
select date_sub('2022-05-15', 5)
语法: add_months(string start_date, int num_months, output_date_format)
返回值: string
描述: 返回开始日期start_date增加num_months月后的日期,output_date_format做为可选参数只在Hive 4.0.0版本后可用。
select add_months('2022-05-15', 5)
语法:months_between(date1, date2)
返回值: double
描述: 返回两日期的间隔月份
select months_between('2022-05-15', '2022-01-15')
格式化日期:date_format函数将字符串或者日期转化为指定格式的日期
select date_format('2022-05-29 20:21:22', 'yyyy-MM-dd')
关于月的计算主要使用trunc()函数的计算
select date_sub(trunc(current_date,'MM'),1);
select trunc(add_months(current_date,-1),'MM')
select trunc(current_date,'MM')
select last_day(current_date());
关于周的计算主要是使用next_day()函数的计算
使用函数next_day获取日期下个星期几的日期,参数周一:MO;周二:TU;周三:WE ;周四:TH ;周五:FR ;周六:SA;周日SU
select date_sub(next_day(current_date,'MO'),7) ;
select date_sub(next_day(current_date,'MO'),1);
select date_sub(next_day(current_date,'MO'),14) ;
select date_sub(next_day(current_date,'MO'),8) ;
主要使用pmod()函数
select pmod(datediff(current_date, '2012-01-01'), 7) = 0 --当等于0是当前天为星期日 select pmod(datediff(current_date, '2012-01-01'), 7) = 1 --当等于1是当前天为星期1 select pmod(datediff(current_date, '2012-01-01'), 7) = 2 --当等于2是当前天为星期2 select pmod(datediff(current_date, '2012-01-01'), 7) = 3 --当等于3是当前天为星期3 select pmod(datediff(current_date, '2012-01-01'), 7) = 4 --当等于4是当前天为星期4 select pmod(datediff(current_date, '2012-01-01'), 7) = 5 --当等于5是当前天为星期5 select pmod(datediff(current_date, '2012-01-01'), 7) = 6 --当等于6是当前天为星期6
利用季度的小公式计算
select concat_ws('-', cast(year(current_date) as string), cast(ceil(month(current_date()) / 3) * 3 - 2 as string), '1');
利用quater()函数+case when转换
select case quarter(current_date)
when 1 then concat(year(current_date), '-01-01')
when 2 then concat(year(current_date), '-04-01')
when 3 then concat(year(current_date), '-07-01')
when 4 then concat(year(current_date), '-10-01')
end as q_first_day
季度算法小公式:
ceil(当前月份 / 3 ):获取当前时间所处的季度(Hive高版本可用quater()函数代替)
一个季度有3个月:
- ceil(当前月份 / 3 ) *3:得到当前月份所处的季度末月份
- ceil(当前月份 / 3 ) *3 -2 :获取当前月份所处的季度初的月份
- ceil(当前月份 / 3 ) *3 + 1 :获取当前月份所处的季度的下一个季度初的月份
当前日期所处的季度末就是:下一个季度月初的时间减去1
select date_sub(concat_ws('-', cast(year(current_date) as string), cast(ceil(month(current_date()) / 3) * 3 + 1 as string), '1')
,1)
select trunc(current_date, 'YYYY')
明年的第一天减去1就是今年的结束日期
select date_sub(trunc(add_months(current_date, 12), 'YYYY'), 1)
根据以上时间的计算方法,我们来生成一张时间维度表,基本上改维度表把以上所有的知识都串起来了。
使用SQL 实现一张日期维度表,包含以下字段:
drop table if exists dim_date;
create table if not exists dim_date(
`date` string comment '日期',
d_week string comment '年内第几周',
weeks string comment '周几',
w_start string comment '周开始日',
w_end string comment '周结束日',
d_month string comment '第几月',
m_start string comment '月开始日',
m_end string comment '月结束日',
d_quarter int comment '第几季',
q_start string comment '季开始日',
q_end string comment '季结束日',
d_year int comment '年份',
y_start string comment '年开始日',
y_end string comment '年结束日'
);
--自然月: 指每月的1 号到那个月的月底,它是按照阳历来计算的。就是从每月1 号到月底,不管这个月
有30 天,31 天,29 天或者28 天,都算是一个自然月。
Hive低版本使用
select `date`
, d_week --年内第几周
, case weekid
when 0 then '周日'
when 1 then '周一'
when 2 then '周二'
when 3 then '周三'
when 4 then '周四'
when 5 then '周五'
when 6 then '周六'
end as weeks -- 周
, date_sub(next_day(`date`, 'MO'), 7) as w_start --周一
, date_sub(next_day(`date`, 'MO'), 1) as w_end -- 周日_end
-- 月份日期
, monthid as d_month
, m_start
, m_end
-- 季节
, quarterid as d_quart
, concat_ws('-', cast(d_year as string), cast(quarterid * 3 - 2 as string), '1') as q_start --季开始日
, date_sub(concat_ws('-', cast(d_year as string), cast(quarterid * 3 + 1 as string), '1'), 1) as q_end --季结束日
, d_year
, y_start
, y_end
from (
select `date`
, pmod(datediff(`date`, '2012-01-01'), 7) as weekid
--获取周几
, month(`date`) as monthid
--获取月份
, ceil(month(`date`) / 3) as quarterid
--获取季节id
, year(`date`) as d_year
-- 获取年份
, trunc(`date`, 'YYYY') as y_start
--年开始日
, date_sub(trunc(add_months(`date`, 12), 'YYYY'), 1) as y_end --年结束日
, trunc(`date`, 'MM') as m_start
--当月第一天
, last_day(`date`) as m_end
--当月最后一天
, weekofyear(`date`) as d_week
--年内第几周
from (
-- '2021-01-01'是开始日期, '2022-05-31'是截止日期
select date_add('2021-01-01', t0.pos) as `date`
from (
select posexplode(split(repeat('o', datediff('2022-05-31', '2021-01-01')), 'o'))
) t0
) t1
) t2;
或Hive高版本使用
select `date`
, d_week --年内第几周
, case weekid
when 0 then '周日'
when 1 then '周一'
when 2 then '周二'
when 3 then '周三'
when 4 then '周四'
when 5 then '周五'
when 6 then '周六'
end as weeks -- 周
, date_sub(next_day(`date`, 'MO'), 7) as w_start --周一
, date_sub(next_day(`date`, 'MO'), 1) as w_end -- 周日_end
-- 月份日期
, monthid as d_month
, m_start
, m_end
-- 季节
, quarterid as d_quart
, concat_ws('-', cast(d_year as string), lpad(cast(quarterid * 3 - 2 as string),2,0), '1') as q_start --季开始日
, date_sub(concat_ws('-', cast(d_year as string), cast(quarterid * 3 + 1 as string), '1'), 1) as q_end --季结束日
, d_year
, y_start
, y_end
from (
select `date`
, dayofweek(`date`) -1 as weekid
--获取周几
, month(`date`) as monthid
--获取月份
, quarter(`date`) as quarterid
--获取季节id
, year(`date`) as d_year
-- 获取年份
, trunc(`date`, 'YYYY') as y_start
--年开始日
, date_sub(trunc(add_months(`date`, 12), 'YYYY'), 1) as y_end --年结束日
, trunc(`date`, 'MM') as m_start
--当月第一天
, last_day(`date`) as m_end
--当月最后一天
, weekofyear(`date`) as d_week
--年内第几周
from (
-- '2021-01-01'是开始日期, '2022-05-31'是截止日期
select date_add('2021-01-01', t0.pos) as `date`
from (
select posexplode(split(repeat('o', datediff('2022-05-31', '2021-01-01')), 'o'))
) t0
) t1
) t2;
本文总结了关于Hive中时间函数的使用及时间维度表的生成方法,时间维度表及时间函数在数据开发中经常被用到,这块需要切实掌