Order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序,即使设置了多个Reduce,程序依然会按照一个Reduce进行排序)。Order by全局排序,又一个缺点,就是只有一个Reducer,会导致数据规模较大是,消耗较长的计算时间。
案例演示:
-- 创建一个分数表
create table score(
stu_id int,
stu_name string,
stu_class string,
stu_score double
);
-- 插入数据
insert into score values
(1,'zhangsan','math',90),
(1,'zhangsan','English',82),
(1,'zhangsan','Chinese',92),
(2,'lisi','math',87),
(2,'lisi','English',95),
(2,'lisi','Chinese',85),
(3,'wangwu','math',94),
(3,'wangwu','English',93),
(3,'wangwu','Chinese',90);
-- 按成绩降序排列
select * from score order by stu_score desc;
sort by 不是全局排序,其在数据进行reducer前完成排序。使用sort by是可以指定执行的reduce的个数set mapred.reduce.tasks=n
,对输出的数据再执行归并排序,即可得到全部结果。
案例演示:
#设置reducer个数为3
set mapred.reduce.tasks=3;
#用sort by 成绩 按降序排序
select * from score sort by stu_score desc;
distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by 后面列,对应reducer的个数进行并发,默认是采用hash算法。sort by为每个reduce产生一个排序文件。一般情况下,distribute by经常和sort by配合使用。
案例演示:
# distribute by和sort by连用,按每个学生分类,并进行科目成绩排序
select * from score distribute by stu_id sort by stu_id asc,stu_score desc;
注:这个select语句是通过按stu_id分区,并且排序,排序的规则是用stu_id与分区数取余,余数小的排在前面,然后再进行区内对成绩排序。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒叙排序,不能指定排序规则。
基础聚合函数
注意事项
排序,聚合,分析
ROW_NUMBER()
对所有数值输出不同的序号,序号唯一连续
案例演示:
select *,ROW_NUMBER() OVER () AS row_num from score;
RANK()
对相同数值,输出相同的序号,下一个序号跳过(1,1,3)
select *,RANK() OVER (PARTITION BY stu_id ORDER BY stu_score) AS rank from score;
注:因为数据中没有重复向,不太好观察,可以自行插入重复项进行观察。
DENSE_RANK()
对相同数值,输出相同的序号,下一个序号连续(1,1,2)
select *,DENSE_RANK() OVER (PARTITION BY stu_id ORDER BY stu_score) AS dense_rank from score;
NLITE(n)
将有序的数据集合平均分配到n个桶中, 将桶号分配给每一行,根据桶号,选取前或后 n分之几的数据。
select *,NTILE(3) OVER(PARTITION BY stu_id ORDER BY stu_score) AS ntile from score;
PERCENT_RANK()
(目前排名- 1)/(总行数- 1),值相对于一组值的百分比排名
select *,PERCENT_RANK() OVER(PARTITION BY stu_id ORDER BY stu_score) AS percent_rank from score;
select *,LEAD(stu_score,2) OVER(PARTITION BY stu_id) AS lead from score;
select *,LAG(stu_score,2) OVER(PARTITION BY stu_id) AS lead from score;
select *,FIRST_VALUE(stu_score) OVER(PARTITION BY stu_id) AS first_value from score;
select *,LAST_VALUE(stu_score) OVER(PARTITION BY stu_id) AS last_value from score;