一、排序函数
数据分析中,排序的需求场景基础且常见,如计算消费金额TOP100的客户等,为此首先介绍基于效率优化和场景应用不同的三种排序函数。
Order by
order by语句用于对查询结果集执行全局排序,所有数据集中在一个reduce中进行处理,默认按照升序排序(ASC),可以使用关键字DESC进行降序排序;
在hive中使用order by的时候会受到mapred.mode属性的约束,默认为nonstrict模式;如果在strict模式下使用order by,必须使用limit关键字,因为执行order by的时候只能启动单个reduce,如果排序的结果集过大,那么执行时间会非常漫长从而引起报错。
语法:
select *
from order_tb
order by amt desc
-- limit 10
sort by
sort by在每个reduce中对数据进行内部排序,属于局部排序。可以通过设置属性mapred.reduce.tasks指定执行的reduce个数,对输出的数据再执行归并排序得到全部结果,如果设置的reduce个数为1的话,那么sort
by 语句和order by语句输出结果一致。
语法:
select *
from order_tb
sort by amt
distribute by
distribute by会根据指定字段的值,将记录分发到不同的reduce中,但是每个reduce中的数据并不是有序的。默认对指定列取hash值,然后hash值对reduce的个数取模,模数相同的记录进入同一个reduce中。通常,将distribute by和sort by连用,针对数据进行指定划分排序。
语法:
select *
from order_tb
distribute by year
sort by amt
二、窗口排序函数
互联网面试中,经常会向面试者提出计算客户连续登录天数之类的问题,这时就需要灵活应用窗口函数,以下三种窗口排序函数也是必知基础。
Row_number()
rank()
Dense_rank()
语法:Row_number()/rank()/Dense_rank() OVER ( PARTITION BY COL1 ORDER BY COL2 )
三个函数语法和功能一致,都需要和over()一起使用,函数将首先根据PARTITION BY后面的字段进行分组,在分组内部根据ORDER BY后面的字段进行排序,最终输出每组内部排序后的顺序编号,其中order by必须存在,PARTITION BY可以不设置。三者的不同体现在计算结果:
Row_number() :为不重复连续排序,即1、2、3、4、…
rank():为可重复跳跃排序,即1、2、2、4、…
Dense_rank() :为可重复连续排序,即1、2、2、3、…
三、类型转换函数
当把时间作为分区字段,通常会用字符串'20201202'记录时间,再进行日期运算的时候就需要进行类型转换,介绍两种将字符串转换为日期的函数:
cast(expr AS type)
将表达式expr转换为指定type类型,是一种较为常见的类型转换函数,如:cast('0123' as int) ;
需要注意的是,当使用cast将字符串转换为日期格式,字符串必须满足yyyy-MM-dd格式,需严格使用如下格式才能实现日期转换:Cast('2020-12-02'
as date) :输出:2020-12-02
to_date(date_str, format)
将字符串格式的date_str转换为指定的日期格式,也可以使用此日期专用函数实现类型转换,即:to_date('20201202','yyyyMMdd'):输出:2020-12-02
四、条件选择函数
数据处理阶段,经常需要对缺失值进行处理,尤其是表join时需注意空缺值的出现。以下2个函数简洁方便:
ifnull(expr1, expr2)
如果表达式expr1为Null,返回expr2,否则返回expr1。特别适合用于空缺值的填充,如:ifnull(amt , 0) ;
if(expr1, expr2, expr3)
如果表达式expr1成立,返回expr2,否则返回expr3。特别适合空缺值处理与逻辑判断,如:if(id is not null, 1,0) ;
五、聚合计数函数
搭建完底层宽表,针对各种维度进行汇总分析,有时会用到聚合函数:count(),返回一组值的计数值。通常有三种不同的统计方式:
count(*):统计所有行数,不会忽略为null的值;
count(1):用1代表代码行进行统计,等同于统计所有行数;
count(col):统计指定列的行数,忽略值为null的行;
简而言之,count(*)与count(1)执行结果相同,效率有所差异;count(col)与其结果不同;