hive函数

日期函数

(1)时间戳转换

日期格式转换时间戳

unix_timestamp(date,dateformat)不加参数获取当前的时间戳

select unix_timestamp() as time_stamp,unix_timestamp('2018-09-26 9:13:26','yyyy-MM-ddHH:mm:ss') as time_stamp1 from dual;

time_stamp      time_stamp1

1538054001      1537924406

 

时间戳转换日期格式

from_unixtime(timestamp,dateformat)

select from_unixtime(unix_timestamp(),'yyyy-MM-dd HH:mm:ss') asdate_time,from_unixtime(1537924406,'yyyy-MM-dd') as date_time1 from dual;

date_time       date_time1

2018-09-27 21:16:13     2018-09-26

 

(2)日期格式化

date_format(string/date,dateformat)把字符串或者日期转成指定格式的日期

select date_format('2018-09-12','yyyy-MM-dd HH:mm:ss') as date_time,date_format('2018-09-12','yyyyMMdd') as date_time1 from dual;

date_time       date_time1

2018-09-12 00:00:00     20180912

 

to_date(date)返回yyyy-MM-dd日期格式

3、日期加减/月份加减(位移)

对日期进行加减法,date_add函数参数n是正数往后推n天,如果是负数往前推n天,date_sub函数相反

对月份进行加减,add_months 函数参数m是正数往后推m个月,如果是负数往前推m个月

date_add(date,n)

date_sub(date,n)

select date_add('2018-09-27',2) as date1,date_add('2018-09-27',-2) as date2 from dual;

date1   date2

2018-09-29      2018-09-25



add_months(date,m)

select add_months('2018-09-27',1) as month1,add_months('2018-09-27',-1) as month2 from dual;

month1  month2

2018-10-27      2018-08-27

4、日期差/月份差

日期差计算两个日期之间相差多少天,前面的日期减去后面的日期

月份差计算前面的日期减去后面的日期计算月份差,这个结果是按照天数占月分的比值计算得到的,是一个小数,可以自己取整

datediff(date,date1)

select datediff('2018-09-22','2018-08-02') as day_diff,datediff('2018-08-02','2018-09-22') as day_diff1 from dual;

day_diff        day_diff1

51      -51

months_between(date,date1)

select months_between('2018-09-22','2018-08-02') as mon_diff,round(months_between('2018-09-22','2018-08-02')) as mon_diff1 from dual;

mon_diff        mon_diff1

1.64516129      2.0

5、获取月末、月初、年初、当前日期下个星期X的日期

获取月末最后一天

last_day(date)

select last_day('2018-09-30') as date_time,last_day('2018-09-27 21:16:13') as date_time1 from dual;

date_time       date_time1

2018-09-30      2018-09-30

获取月初、年初

trunc(date,format)  format:MONTH/MON/MM, YEAR/YYYY/YY

select trunc('2018-09-27','YY') as date_time,trunc('2018-09-27 21:16:13','MM') as date_time1 from dual;

date_time       date_time1

2018-01-01      2018-09-01

当前日期下个星期X的日期

next_day(date,formate) format:英文星期几的缩写或者全拼

select next_day('2018-09-27','TH') as date_time,next_day('2018-09-27 21:16:13','TU') as date_time1 from dual;

date_time       date_time1

2018-10-04      2018-10-02

 

 

hive条件函数

(1)if函数:if(条件表达式,结果1,结果2)

hive> select if(1=2,100,200) from lxw_dual;
200
hive> select if(1=1,100,200) from lxw_dual;
100

 

(2)coalesce函数:返回参数中的第一个非空值;如果所有值都为null,那么返回null

hive> select COALESCE(null,'100','50′) from lxw_dual;
100

 

(3)case when函数:

  •  CASE a WHEN b THEN c [WHENd THEN e]* [ELSE f] END
  • 如果a等于b,那么返回c;如果a等于d,那么返回e;否则返回f
hive> Select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end from lxw_dual;
mary
hive> Select case 200 when 50 then 'tom' when 100 then 'mary' else 'tim' end from lxw_dual;
tim

 

  • CASE WHEN a THEN b [WHEN cTHEN d]* [ELSE e] END
  • 如果a为TRUE,则返回b;如果c为TRUE,则返回d;否则返回e
hive> select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end from lxw_dual;
mary
hive> select case when 1=1 then 'tom' when 2=2 then 'mary' else 'tim' end from lxw_dual;
tom

 count函数

count(*):所有行进行统计,包括null行

count(1):所有行进行统计,包括null行

count(columc)与count(if(条件)):都是对column中非null进行统计,来一条就统计一条,不关心怎样进行分类

count(distinct  column):去重统计也会排除字段为null的值

使用group by代替distinct

 

count(case when plat=1 then u else null end)

count(distinct case when plat=1 then u else null end)

count(case when (type=2 OR type=6) then u else null end)

count(distinct case when (type=2 OR type=6) then u else null end)

create table t1( a int);
insert into t1 (a) values (1);
insert into t1 (a) values (2);
insert into t1 (a) values (3);
insert into t1 (a) values (NULL);


select count(*) from t1;
4
select count(1) from t1;
4
select count(a) from t1;
3
select count(a>1) from t1;
3
select count(distinct a) from t1;
3
select count(distinct case when a>1 then a else NULL end)  from t1
2

 

count(if)与count(distinct if)小案例:

 

 

表名: user_active_day (用户日活表)

表内容:

user_id(用户id)   user_is_new(是否新用户 1:新增用户 0:老用户) location_city(用户所在地区) partition_date(日期分区)

需求:

  找出20180901至今的xxx地区的用户日活量以及新增用户量

思路:

  筛选日期分区和地区,统计user_id的数量为用户日活量,统计user_is_new = 1的数量为新增用户量.

最开始写的hql语句

select partition_date,count(user_id),
         count(if(user_is_new = 1, user_id, 0))  --注意新增用户量的统计
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

 

 我们使用count(if())来进行筛选统计,但是效果并没有达到,出现的结果如下

20180901    16737  16737

 根本就没有达到筛选的目的,为什么?

这就要从count的机制说起

首先count()是对数据进行计数,说白了就是你来一条数据我计数一条,我不关心你怎么分类,我只对数据计数

每条数据从if()函数出来,还是一条数据,所以count+1

所以count(user_id)跟count(if(user_id))没有任何的区别.

我们稍做修改

select partition_date,count(user_id),
         count(distinct if(user_is_new = 1, user_id, 0))  --注意新增用户量的统计,加了distinct去重
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

结果如下

20180901    16737  261

这次看着就像是对了吧,我们加了distinct进行去重

每次来一条数据先过if()然后再进行去重最后统计.但是实际上结果依旧是错误的.

我们来模拟一下筛选统计的过程

我们有这样四条数据

user_id    user_is_new

   1               1

   2              0

   3              1

   4              0

表中的数据是一条一条遍历的,

(1)当user_id = 1的数据过来的时候,我们先过if函数  user_is_new = 1    ==>  count(distinct user_id = 1), 

然后我们把user_id = 1进行重复判断,我们用一个模拟容器来模拟去重,

从容器里找user_id = 1的数据,发现没有,不重复,所以通过我们把count+1,然后把user_id = 1的数据放入,用于下条去重

(2)当user_id = 2的数据过来的时候,我们先过if函数  user_is_new = 0    ==>  count(distinct 0), 

然后我们把0进行重复判断,

从容器里找0的数据,发现没有,不重复,所以通过我们把count+1,然后把0的数据放入,用于下条去重

(3)当user_id = 3的数据过来的时候,我们先过if函数  user_is_new = 1    ==>  count(distinct user_id = 3), 

然后我们把user_id = 3进行重复判断,

从容器里找user_id = 3的数据,发现没有,不重复,所以通过我们把count+1,然后把user_id = 3的数据放入,用于下条去重

(4)当user_id = 4的数据过来的时候,我们先过if函数  user_is_new = 0    ==>  count(distinct 0), 

然后我们把0进行重复判断,
从容器里找0的数据,发现重复,是之前user_id = 2的时候过if()转化成0的那条数据,所以count不执行

 

 

 

 

 

 

 

 

 

 

 

 

我们通过模拟count(distinct if)过程发现,在count的时候我们把不符合条件的最开始的那条语句也count进去了一次

导致最终结果比正确结果多了1.

我们在原基础语句上再减去1就是正确的hql语句

其实在日常中我们做分类筛选统计的时候一般是用sum来完成的,符合条件sum+1,不符合条件sum+0

select partition_date,count(user_id),
         sum(if(user_is_new = 1, 1, 0))  --用sum进行筛选统计
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

 

 结果如下

20180901    16737  260

 

sum(if)只试用于单个条件判断,如果筛选条件很多,我们可以用sum(case when then else end)来进行多条件筛选

注意,hive中并没有sum(distinct col1)这种使用方式,我们可以使用sum(col) group by col来达到相同效果. 

 

 

 

 

 

 

 

 

posted @ 2019-12-03 22:48  IT界一个小学生  阅读(309)  评论(0编辑  收藏  举报