jjzjj

HiveSql常用的时间维度计算方法(月初、月末、周几)及时间维度 表生成

莫叫石榴姐 2023-09-05 原文

目录

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 时间日期维度表生成


0 基础函数

trunc()

trunc(string date,string format) — 返回日期的最开始日期

目前格式支持:MM(月)YYYY(年)Hive3.0后支持Q表示季度

select trunc(current_date,'MM') --月初
select trunc(current_date,'YY') --年初

 

last_day()

last_day(string date) — 返回该月最后一天的日期

select last_day(current_date());

add_months()

add_months(string date,int months) — 返回months月之后的date,months可以是负数

select add_months(current_date(),1);

 

current_date()/current_date

当前日期(天)

select current_date

next_day

next_day(string date,string dayOfWeek) — 返回date之后的下一个周的dayOfWeek的天

求当前日期的下周一时间

select next_day(current_date,'MO')

pmod()

pmod(int a, int b)

pmod(double a, double b)

返回a除以b的余数的绝对值


select pmod(10,4)

to_date 

语法:to_date(string timestamp)
返回值: 2.1.0版本前返回string,2.1.0版本后返回date
描述: 将一个字符串date按照"yyyy-MM-dd"格式转成日期值.

select to_date(current_timestamp)

 year

语法:year(string date)
返回值:int
描述:提取日期中的年份部分

select year(current_timestamp)

month 

语法:month(string date)
返回值: int
描述:提取日期中的月份部分

select month(current_timestamp)

hour 

语法:hour(string date)
返回值:int
描述:提取日期中的小时部分

select hour(current_timestamp)

dayofweek

获取当前日期的星期几。这里本周的第一天是周日,使用时候注意转换。Hive低版本没有该函数,Hive2.1版本之后才有,如果版本较低建议使用pmod方法获取当前日期的星期几,参考下文。

select dayofweek('2022-05-29 20:21:22')

 

weekofyear 

语法:weekofyear(string date)
返回值:int
描述: 返回指定日期处于当年的第几周

select weekofyear('2022-05-29') as weekofyear;

quarter

获取当前日期所处的季度

select quarter('2022-05-29 20:21:22')

低版本没有该函数,可以用ceil(month(date) / 3)来代替

select CEIL(month('2022-05-29 20:21:22') / 3)

 datediff

语法:datediff(string enddate, string startdate)
返回值: int
描述: 返回两指定日期之间的天数

select datediff('2022-05-30', '2022-05-15')

date_add 

语法: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_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 

语法: 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

语法:months_between(date1, date2)
返回值: double
描述: 返回两日期的间隔月份

select months_between('2022-05-15', '2022-01-15')

 date_format

格式化日期:date_format函数将字符串或者日期转化为指定格式的日期

select date_format('2022-05-29 20:21:22', 'yyyy-MM-dd')

1 关于月的计算

关于月的计算主要使用trunc()函数的计算

1.1上月末

select date_sub(trunc(current_date,'MM'),1);

1.2上月初

select trunc(add_months(current_date,-1),'MM')

 

 1.3本月初

select trunc(current_date,'MM')

1.4 本月末

select last_day(current_date());

2 关于周计算

关于周的计算主要是使用next_day()函数的计算

使用函数next_day获取日期下个星期几的日期,参数周一:MO;周二:TU;周三:WE ;周四:TH ;周五:FR ;周六:SA;周日SU

2.1 本周一

select date_sub(next_day(current_date,'MO'),7) ;

2.2 本周末

select date_sub(next_day(current_date,'MO'),1);

 2.3 上周一

select date_sub(next_day(current_date,'MO'),14) ;

 2.4上周末

select date_sub(next_day(current_date,'MO'),8) ;

2.5 根据当前日期得出星期几

主要使用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

3 关于季度计算

3.1季度初方法一

利用季度的小公式计算

select concat_ws('-', cast(year(current_date) as string), cast(ceil(month(current_date()) / 3) * 3 - 2 as string), '1');

3.2 季度初方法二

利用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

 3.3 获取季度末的方法

季度算法小公式:

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)

4 关于年计算

4.1 年开始日期

select trunc(current_date, 'YYYY')

 4.2 年结束的日期

明年的第一天减去1就是今年的结束日期

select date_sub(trunc(add_months(current_date, 12), 'YYYY'), 1)

5 时间日期维度表生成

根据以上时间的计算方法,我们来生成一张时间维度表,基本上改维度表把以上所有的知识都串起来了。

使用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;

6 小结

本文总结了关于Hive中时间函数的使用及时间维度表的生成方法,时间维度表及时间函数在数据开发中经常被用到,这块需要切实掌

有关HiveSql常用的时间维度计算方法(月初、月末、周几)及时间维度 表生成的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  9. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  10. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

随机推荐