HIVE语句(上)

本文介绍了HIVE的基础知识,包括HIVE是什么、用途及使用方式。深入讲解了HIVE的语句,如建表、内部表和外部表、分区、导入导出数据、存储文件格式、INSERT操作、分桶表、GROUP BY和HAVING语句,以及JOIN和排序等。此外,还提供了一个关于成绩分区的MapReduce实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、了解HIVE

1、是什么

  • 是一个可以将sql翻译为MR程序的工具
  • 支持用户将HDFS上的文件映射为表结构,用户可以输入SQL进行查询分析
  • 将用户定义的库、表结构等信息存储在hive的元数据库中

2、用途

构建大数据体系下的数据仓库

3、使用方式

1)方式一:交互式查询

将hive启动为一个服务: bin/hiveserver ,然后可以在任意一台机器上使用beeline客户端连接hive服务,进行交互式查询

2)方式二:将hive作为命令一次性运行

事先将sql语句写入一个文件比如 q.hql ,然后用hive命令执行:bin/hive -f q.hql

3)方式三:将方式二写入一个xxx.sh脚本中

二、HIVE语句

1、三种执行模式

[root@node01 ~]# hive -e "use default;create table test_1(id int,name string);"
OK
Time taken: 2.453 seconds
OK
Time taken: 1.37 seconds
[root@node01 ~]# hive -e "desc test_1;"
OK
id                  	int                 	                    
name                	string              	                    
Time taken: 2.939 seconds, Fetched: 2 row(s)
[root@node01 home]# vi a.hql 
	1,xiaoming,20
	2,xiaowang,22
[root@node01 home]# vi /home/userinfo.txt
	use default;
	create table test_2(id int,name string,age int)
	row format delimited
	fields terminated by ',';
	load data local inpath '/home/userinfo.txt' into table test_2;
	select count(*) from test_2;
[root@node01 home]# hive -f a.hql   #运行
[root@node01 home]# hive -e "select * from test_2;"
OK
1	xiaoming	20
2	xiaowang	22
NULL	NULL	NULL
Time taken: 3.608 seconds, Fetched: 3 row(s)
[root@node01 home]# cd /usr/local/src/hive-1.2.1/bin/
[root@node01 bin]# ./hiveserver2
#光标定位到下一行不动
[root@node02 bin]# ./beeline 
Beeline version 1.2.1 by Apache Hive
beeline> !connect jdbc:hive2://node01:10000
Connecting to jdbc:hive2://node01:10000
Enter username for jdbc:hive2://node01:10000: root
Enter password for jdbc:hive2://node01:10000: 
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://node01:10000>                #连接到node01服务端
0: jdbc:hive2://node01:10000> 

#可以查询node01中的内容(以表格形式)
0: jdbc:hive2://node01:10000> show databases;
+----------------+--+
| database_name  |
+----------------+--+
| default        |
+----------------+--+
1 row selected (3.375 seconds)

0: jdbc:hive2://node01:10000> show tables;
+-----------+--+
| tab_name  |
+-----------+--+
| test_1    |
| test_2    |
+-----------+--+
2 rows selected (0.198 seconds)

0: jdbc:hive2://node01:10000> select * from test_2;
+------------+--------------+-------------+--+
| test_2.id  | test_2.name  | test_2.age  |
+------------+--------------+-------------+--+
| 1          | xiaoming     | 20          |
| 2          | xiaowang     | 22          |
| NULL       | NULL         | NULL        |
+------------+--------------+-------------+--+
3 rows selected (1.925 seconds)

#node02中每进行一条,node01中都会打印一个OK(因为命令都发到node01上的服务端执行)
[root@node01 bin]# ./hiveserver2 
OK
OK
OK

2、建表

1)表定义信息会被记录到hive的元数据中(mysql的hive库)

在hdfs上的hive库目录中创建一个跟表名一致的文件夹
在这里插入图片描述
表中没有数据
在这里插入图片描述

#查询test_1中的字段信息
[root@node01 home]# hive -e "desc test_1;"
id                  	int                 	                    
name                	string              	                    
sge                 	int                 	                    
Time taken: 2.572 seconds, Fetched: 3 row(s)
#有字段id和name,age,我们创建一个文件,好后上传到hdfs对应的test_1表对应的目录下
[root@node01 home]# vi test_1.txt
	1,zhangsan,12
	2,lisi,32
[root@node01 home]# hadoop fs -put test_1.txt /user/hive/warehouse/test_1

表中有数据
在这里插入图片描述

改进

#以上结果
hive> select * from test_1;
OK
NULL	NULL	NULL
NULL	NULL	NULL
#建表时没有指定分隔符
#删除表
hive> drop table test_1;
#重新创建一个带有分隔符的表
hive> create table test_1(id string,name string,age int)
    > row format delimited
    > fields terminated by ',';
#重新上传文件
[root@node01 home]# hadoop fs -put test_1.txt /user/hive/warehouse/test_1
#查看结果
hive> select * from test_1;
OK
1	zhangsan	12
2	lisi	32

#再创建一个文件
[root@node01 home]# vi test_1.txt.1
	3,xiaoming,14
	4
	5,lili3
[root@node01 home]# hadoop fs -put test_1.txt.1 /user/hive/warehouse/test_1
#不填默认为null
hive> select * from test_1;
OK
1	zhangsan	12
2	lisi	32
3	xiaoming	14
4	NULL	NULL
5	lili3	NULL
	NULL	NULL

3、内部表和外部表

1)内部表

#创建表
hive> create table t_2(id int,name string,salary bigint,add string)
    > row format delimited
    > fields terminated by ','
    > location '/aa/bb';
    
[root@node01 home]# vi /home/salary.txt
1,apple,4,weifang
2,banana,2,hainan
3,orange,4,hunan
4,liulian,100,mangu

#运行
hive> load data local inpath '/home/salary.txt' into table t_2;
hive> select * from t_2;
OK
1	apple	4	weifang
2	banana	2	hainan
3	orange	4	hunan
4	liulian	100	mangu

在这里插入图片描述

#删除表
hive> drop table t_2;

hdfs中的文件也会被删除
在这里插入图片描述

2)外部表(external)

hive> create external table t_3(id int,name string,salary bigint,add string)
    > row format delimited
    > fields terminated by ','
    > location'/aa/bb';

[root@node01 home]# hadoop fs -put salary.txt /aa/bb/
[root@node01 home]# hadoop fs -cat /aa/bb/salary.txt
1,apple,4,weifang
2,banana,2,hainan
3,orange,4,hunan
4,liulian,100,mangu

hive> select * from t_3;
OK
1	apple	4	weifang
2	banana	2	hainan
3	orange	4	hunan
4	liulian	100	mangu

在这里插入图片描述

#删除表
hive> drop table t_3;

数据目录不会删除
在这里插入图片描述

3)小结

  • 说明: location '/aa/bb’是hdfs的目录
  • 区别: 内部表的目录由hive创建在默认的仓库目录下:/user/hive/warehouse/…(也可以指定)
    外部表的目录由用户建表时自己指定: location ‘/位置/’
    drop一个内部表时,表的元信息和表数据目录都会被删除;
    drop一个外部表时,只删除表的元信息,表的数据目录不会删除;
  • 意义: 通常,一个数据仓库系统,数据总有一个源头,而源头一般是别的应用系统产生的,其目录无定法,为了方便映射,就可以在hive中用外部表进行映射;并且,就算在hive中把这个表给drop掉,也不会删除数据目录,也就不会影响到别的应用系统。

4、 分区关键字 PARTITIONED BY

#创建
hive> create table test_44(ip string,url string,staylong int)
    > partitioned by(day string)
    > row format delimited
    > fields terminated by ',';
    
[root@node01 home]# vi pv.data.2019-05-10
	192.168.9.10,www.a.com,1000
	192.168.10.10,www.b.com,100
	192.168.11.10,www.c.com,900
	192.168.12.10,www.d.com,100
	192.168.13.10,www.e.com,2000
	
hive> load data local inpath '/home/pv.data.2019-05-10' into table test_44 partition(day='2019-05-10');

在这里插入图片描述

[root@node01 home]# vi pv.data.2019-05-11
	192.168.9.11,www.f.com,100
	192.168.10.12,www.g.com,10
	192.168.11.13,www.h.com,90
	192.168.12.14,www.i.com,10
	192.168.13.15,www.g.com,200
	
hive> load data local inpath '/home/pv.data.2019-05-11' into table test_44 partition(day='2019-05-11');

在这里插入图片描述

#查询
hive> select * from test_44;
OK
192.168.9.10	www.a.com	1000	2019-05-10
192.168.10.10	www.b.com	100	2019-05-10
192.168.11.10	www.c.com	900	2019-05-10
192.168.12.10	www.d.com	100	2019-05-10
192.168.13.10	www.e.com	2000	2019-05-10
192.168.9.11	www.f.com	100	2019-05-11
192.168.10.12	www.g.com	10	2019-05-11
192.168.11.13	www.h.com	90	2019-05-11
192.168.12.14	www.i.com	10	2019-05-11
192.168.13.15	www.g.com	200	2019-05-11
Time taken: 0.745 seconds, Fetched: 10 row(s)

#分区查询
hive> select * from test_44 where day='2019-05-11';
OK
192.168.9.11	www.f.com	100	2019-05-11
192.168.10.12	www.g.com	10	2019-05-11
192.168.11.13	www.h.com	90	2019-05-11
192.168.12.14	www.i.com	10	2019-05-11
192.168.13.15	www.g.com	200	2019-05-11
Time taken: 2.097 seconds, Fetched: 5 row(s)

#查询某天访问人数
hive> select distinct ip from test_44 where day='2019-05-11';

5、导入、导出数据

1)导入数据

#将hive运行所在机器的本地磁盘上的文件导入表中
hive> load data local inpath '/home/pv.data.2019-05-11' overwrite into table test_4 partition(day=”2019-05-12”); 
#覆盖test_4表的day=”2019-05-12”分区 的数据

#将hdfs中的文件导入表中
hive> load data inpath '/user.data.2' into table t_1;
#不加local关键字,则是从hdfs的路径中移动文件到表目录中; 

#从别的表查询数据后插入到一张新建表中
hive> create table t_1_iz
    > as
    > select id,name from test_1;
        
hive> select * from t_1_iz;
OK
1	zhangsan
2	lisi
3	xiaoming
4	NULL
5	lili3
	NULL

#从别的表查询数据后插入到一张已存在的表中
	#新建一个字段一样的表
hive> create table t_1_hd like test_1;
	#从test_1中查询一些数据出来插入到t_1_hd中:
hive> insert into table t_1_hd
    > select
    > id,name,age
    > from test_1
    > where name='zhangsan';
    #结果
hive> select * from t_1_hd;
OK
1	zhangsan	12

[root@node01 home]# vi test_1.txt.2
[root@node01 home]# hadoop fs -put test_1.txt.2 /user/hive/warehouse/test_1
	6,lxx,45
	7,xxl,36
	8,lss,13
	
hive> insert into table t_1_hd
    > select
    > id,name,age
    > from test_1
    > where name like'%l';
hive> select * from t_1_hd;
OK
1	zhangsan	12
7	xxl	36

hive> insert overwrite table t_1_hd
    > select
    > id,name,age
    > from test_1
    > where name like'l%';
hive> select * from t_1_hd;
OK
2	lisi	32
5	lili3	NULL
6	lxx	45
8	lss	13

#关于分区数据导入另外一张表
	#建表
hive> create table t_4_hd like test_4;
	#导入
hive> insert into table t_4_hd partition(day='2019-04-10')select ip,url,staylong from test_44 where day='2019-05-10';
	#查看
hive> select * from t_4_hd;
OK
192.168.9.10	www.a.com	1000	2019-04-10
192.168.10.10	www.b.com	100	2019-04-10
192.168.11.10	www.c.com	900	2019-04-10
192.168.12.10	www.d.com	100	2019-04-10
192.168.13.10	www.e.com	2000	2019-04-10

2)导出数据

#将数据从hive的表中导出到hdfs的目录中
#没有此目录将会自动生成
hive> insert overwrite directory '/aa/test_1'
    > select * from test_1 where name='xxl';

在这里插入图片描述

hive> insert overwrite local directory '/aa/test_1_2'
    > row format delimited
    > fields terminated by ','
    > select * from test_1 limit 100;

在这里插入图片描述

#输出为表格形式
[root@node01 test_1_2]# hive -e "select * from test_1" | tr "\t" "," > result.csv
[root@node01 test_1_2]# ll
总用量 8
-rw-r--r-- 1 root root  98 8月  29 02:19 000000_0
-rw-r--r-- 1 root root 112 8月  29 02:26 result.csv

在这里插入图片描述

#将数据从hive的表中导出到本地磁盘目录中
hive> insert overwrite local directory'/aa/bb'
    > select * from test_1;


[root@node01 test_1_2]# cd /aa/bb/
[root@node01 bb]# ll
总用量 4
-rw-r--r-- 1 root root 98 8月  29 04:11 000000_0
[root@node01 bb]# cat 000000_0 
1zhangsan12
2lisi32
3xiaoming14
4\N\N
5lili3\N
\N\N
6lxx45
7xxl36
8lss13
\N\N

6、HIVE的存储文件格式

HIVE支持很多种文件格式: SEQUENCE FILE | TEXT FILE | PARQUET FILE | RC FILE

#创建一张t_seq,指定文件格式sequencefile
hive> create table t_seq(id int,name string)
    > stored as sequencefile;
#往表t_seq中插入数据
hive> insert into table t_seq
    > select * from test_1;
#hive会生成sequence文件插入表目录中

7、表的分区

#查看表的分区
hive> show partitions test_44;
OK
day=2019-05-10
day=2019-05-11

#添加分区
hive> alter table test_44 add partition(day='2019-05-12')partition(day='2017-04-13');
hive> show partitions test_44;
OK
day=2017-04-13
day=2019-05-10
day=2019-05-11
day=2019-05-12

#向新增分区中导入数据
	#load
hive> load data local inpath '/aa/pv.data.2019-05-12' into table test_44 partition(day='2019-05-12');
hive> select * from test_44 where day='2019-05-12';
OK
192.168.9.11	www.f.com	100	2019-05-12
192.168.10.12	www.g.com	12	2019-05-12
192.168.11.13	www.h.com	12	2019-05-12
192.168.12.14	www.i.com	12	2019-05-12

	#insert
hive> insert into table test_44 partition(day='2019-05-13')
    > select ip,url,staylong from test_44 where day='2019-05-11' and staylong>20;
hive> select * from test_44 where day='2019-05-13';
OK
192.168.9.11	www.f.com	100	2019-05-13
192.168.11.13	www.h.com	90	2019-05-13
192.168.13.15	www.g.com	200	2019-05-13

#删除分区
hive> alter table test_44 drop partition(day='2019-05-13');
hive> select * from test_44;
OK
192.168.9.10	www.a.com	1000	2019-05-10
192.168.10.10	www.b.com	100	2019-05-10
192.168.11.10	www.c.com	900	2019-05-10
192.168.12.10	www.d.com	100	2019-05-10
192.168.13.10	www.e.com	2000	2019-05-10
192.168.9.11	www.f.com	100	2019-05-11
192.168.10.12	www.g.com	10	2019-05-11
192.168.11.13	www.h.com	90	2019-05-11
192.168.12.14	www.i.com	10	2019-05-11
192.168.13.15	www.g.com	200	2019-05-11
192.168.9.11	www.f.com	100	2019-05-12
192.168.10.12	www.g.com	12	2019-05-12
192.168.11.13	www.h.com	12	2019-05-12
192.168.12.14	www.i.com	12	2019-05-12

8、表的列定义

#查看表的定义
hive> desc t_seq;
OK
id                  	string              	                    
name                	string              	                    
age                 	int           

#添加列
hive> alter table t_seq add columns(address string);
hive> desc t_seq;
OK
id                  	string              	                    
name                	string              	                    
age                 	int                 	                    
address             	string              	     

#全部替换
hive> alter table t_seq replace columns(id int,name string,addredd string,age int);
hive> desc t_seq;
OK
id                  	int                 	                    
name                	string              	                    
addredd             	string              	                    
age                 	int               

#修改已存在的列定义
hive> alter table t_seq change id uid string;
hive> desc t_seq;
OK
uid                 	string              	                    
name                	string              	                    
addredd             	string              	                    
age                 	int     

9、显示命令

#显示所有库
hive> show databases;
#显示所有表
hive> show tables;
#显示表的分区
hive> show partitions test_4;
#显示hive中所有的内置函数
hive> show functions
#显示表定义
hive> desc test_4;
#显示表定义的详细信息
hive> desc extended test_4;
#显示表定义的详细信息,并且用比较规范的格式显示
hive> desc formatted test_4;
#清空表数据,保留表结构
hive> truncate table test_4_st_200;
hive> desc test_44;
OK
ip                  	string              	                    
url                 	string              	                    
staylong            	int                 	                    
day                 	string              	                    
	 	 
#Partition Information	 	 
#col_name            	data_type           	comment             
	 	 
day                 	string              	                    
Time taken: 0.177 seconds, Fetched: 9 row(s)
hive> select * from test_44;
OK
Time taken: 0.225 seconds

#设置本地运行hive的mapreduce,不提交给yarn
hive>set hive.exec.mode.local.auto=true;

10、insert(插入)

1)加载数据到表中

load、insert(请到前面寻找)

2)插入数据

#插入单条数据
hive> insert into table t_seq values('9','haha','beijing','28');

#多重插入
#从test_44中筛选出不同的数据,插入另外两张表中;
hive> create table test_4_st_200 like test_44;
	#添加分区只能是day
hive> alter table test_4_st_200 add partition(day='lt200');

	#将staylong小于200的数据添加到test_4_st_200,day='lt200'分区中
hive> insert into table test_4_st_200 partition(day='lt200')
	>select ip,url,staylong from test_44 where staylong<200;
hive> select * from test_4_st_200;
OK
192.168.10.10	www.b.com	100	lt200
192.168.12.10	www.d.com	100	lt200
192.168.9.11	www.f.com	100	lt200
192.168.10.12	www.g.com	10	lt200
192.168.11.13	www.h.com	90	lt200
192.168.12.14	www.i.com	10	lt200

#将staylong大于200的数据添加到test_4_st_200,day='gt200'分区中
hive> insert into table test_4_st_200 partition(day='gt200')
	>select ip,url,staylong from test_44 where staylong>200;
hive> select * from test_4_st_200;
OK
192.168.9.10	www.a.com	1000	gt200
192.168.11.10	www.c.com	900	gt200
192.168.13.10	www.e.com	2000	gt200
192.168.10.10	www.b.com	100	lt200
192.168.12.10	www.d.com	100	lt200
192.168.9.11	www.f.com	100	lt200
192.168.10.12	www.g.com	10	lt200
192.168.11.13	www.h.com	90	lt200
192.168.12.14	www.i.com	10	lt200

**但是以上实现方式有一个弊端,两次筛选job,要分别启动两次mr过程,要对同一份源表数据进行两次读取
如果使用多重插入语法,则可以避免上述弊端,提高效率:源表只要读取一次即可**
hive> from test_44
	>insert into table test_4_st_200 partition(day='lt200')
	>select ip,url,staylong where staylong<200
	>insert into table test_4_st_200 partition(day='gt200')
	>select ip,url,staylong where staylong>200;
hive> select * from test_4_st_200;
OK
192.168.9.10	www.a.com	1000	gt200
192.168.11.10	www.c.com	900	gt200
192.168.13.10	www.e.com	2000	gt200
192.168.9.10	www.a.com	1000	gt200
192.168.11.10	www.c.com	900	gt200
192.168.13.10	www.e.com	2000	gt200
192.168.10.10	www.b.com	100	lt200
192.168.12.10	www.d.com	100	lt200
192.168.9.11	www.f.com	100	lt200
192.168.10.12	www.g.com	10	lt200
192.168.11.13	www.h.com	90	lt200
192.168.12.14	www.i.com	10	lt200
192.168.10.10	www.b.com	100	lt200
192.168.12.10	www.d.com	100	lt200
192.168.9.11	www.f.com	100	lt200
192.168.10.12	www.g.com	10	lt200
192.168.11.13	www.h.com	90	lt200
192.168.12.14	www.i.com	10	lt200

11、分桶表

参考:https://www.cnblogs.com/kouryoushine/p/7809299.html

1)定义

将数据按照指定的字段进行分成多个桶中去,就是将数据按照字段进行划分,可以将数据按照字段划分到多个文件当中去

2)使用

#开启桶表功能
hive> set hive.enforce.bucketing=true;
#设置reduce个数
hive> set mapreduce.job.reduces=3;
#创建桶表
hive> create table course(c_id string,c_name string,t_id string)clustered by(c_id)into 3 buckets row format delimited fields terminated by '\t';

桶表的数据加载: 由于通过hdfs dfs -put文件或者通过load data均不好使,所以只能通过insert overwrite

创建普通表,并通过insert overwrite的方式将普通表的数据通过查询的方式加载到桶表当中去

#创建普通表:
hive> create table course_common (c_id string,c_name string,t_id string) row format delimited fields terminated by '\t';
#普通表中加载数据
hive> load data local inpath '/home/course.csv' into table course_common;
hive> insert overwrite course select * from course_common;

12、GROUP BY语句

#创建分区表语法
hive> create table score(s_id string,c_id string, s_score int) partitioned by (month string) row format delimited fields terminated by '\t';
#加载数据到分区表中
hive> load data local inpath '/home/score.csv' into table score partition (month='201909');

GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
案例实操:

#计算每个学生的平均分数
hive> select s_id ,avg(s_score) from score group by s_id;
#注意group  by的字段,必须是select后面的字段,select后面的字段不能比group  by的字段多

#计算每个学生最高成绩
hive> select s_id ,max(s_score) from score group by s_id;

13、HAVING语句

1)having与where不同点

  • where针对表中的列发挥作用,查询数据;having针对查询结果中的列发挥作用,筛选数据。
  • where后面不能写分组函数,而having后面可以使用分组函数。
  • having只用于group by分组统计语句。

2)案例实操:

#求每个学生的平均分数
hive> select s_id ,avg(s_score) from score group by s_id;
#求每个学生平均分数大于85的人
hive> select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;

14、JOIN语句

等值JOIN
老版本中,不支持非等值的join
在新版中:1.2.0后,都支持非等值join

1)案例

①查询分数对应的姓名
#创建学生表老师表:
hive> create table student (s_id string,s_name string,s_birth string , s_sex string ) row format delimited fields terminated by '\t';
hive> create table teacher (t_id string,t_name string) row format delimited fields terminated by '\t';
#加载数据
hive> load data local inpath '/home/teacher.csv' into table teacher;
hive> load data local inpath '/home/student.csv' into table student;

SELECT s.s_id,s.s_score,stu.s_name,stu.s_birth  FROM score s LEFT JOIN student stu ON s.s_id = stu.s_id;

好处:

  • 使用别名可以简化查询。
  • 使用表名前缀可以提高执行效率。
②实例
合并老师与课程表
select * from teacher t join course c on t.t_id = c.t_id;

#内连接(INNER JOIN):只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。
hive> select * from teacher t inner join course c on t.t_id = c.t_id;

#左外连接(LEFT OUTER JOIN):JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
#查询老师对应的课程
hive> select * from teacher t left join course c on t.t_id = c.t_id;

#右外连接(RIGHT OUTER JOIN):JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。
hive> select * from teacher t right join course c on t.t_id = c.t_id;

#满外连接(FULL OUTER JOIN):将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
hive> SELECT * FROM teacher t FULL JOIN course c ON t.t_id = c.t_id ;

#多表连接
#注意:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
#多表连接查询,查询老师对应的课程,以及对应的分数,对应的学生
#设置表头
hive> set hive.cli.print.header=true;
	>select * from teacher t 
	>left join course c 
	>on t.t_id = c.t_id
	>left join score s 
	>on s.c_id = c.c_id
	>left join student stu 
	>on s.s_id = stu.s_id;

大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先启动一个MapReduce job对表teacher和表course进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表score;进行连接操作。
排序

15、排序

1)全局排序

Order By:全局排序,一个reduce

  • 使用 ORDER BY 子句排序
    ASC(ascend): 升序(默认)
    DESC(descend): 降序
  • ORDER BY 子句在SELECT语句的结尾

案例实操

#查询学生的成绩,并按照分数降序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;

#查询学生的成绩,并按照分数升序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score asc;

#按照别名排序
	#按照分数的平均值排序
select s_id ,avg(s_score) avg from score group by s_id order by avg;

#多个列排序
	#按照学生id和平均成绩进行排序
select s_id ,avg(s_score) avg from score group by s_id order by s_id,avg;

每个MapReduce内部排序(Sort By)局部排序
#Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。

#设置reduce个数
set mapreduce.job.reduces=3;
#查看设置reduce个数
set mapreduce.job.reduces;
#查询成绩按照成绩降序排列
select * from score sort by s_score;
#将查询结果导入到文件中(按照成绩降序排列)
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score;

2)分区排序(DISTRIBUTE BY)

Distribute By: 类似MR中partition,进行分区,结合sort by使用。
注意:

  • Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。
  • 对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。

案例实操:
先按照学生id进行分区,再按照学生成绩进行排序。

#设置reduce的个数,将我们对应的s_id划分到对应的reduce当中去
hive> set mapreduce.job.reduces=7;
#通过distribute by  进行数据的分区
hive> insert overwrite local directory '/home/sort' select * from score distribute by s_id sort by s_score;

16、CLUSTER BY

当distribute by和sort by字段相同时,可以使用cluster by方式。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒序排序,不能指定排序规则为ASC或者DESC。

#以下两种写法等价
hive> select * from score cluster by s_id;
hive> select * from score distribute by s_id sort by s_id;

三、关于成绩分区的MapReduce实例

course
在这里插入图片描述
score
在这里插入图片描述
student
在这里插入图片描述
teacher
在这里插入图片描述

package com.doit.scorep;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

public class ScorePartitioner extends Partitioner<Text,Text> {

//    @Override
//    public int getPartition(Text score, Text id, int i) {
//
//        int scoreInt = Integer.parseInt(score.toString());
//        if(scoreInt>=90 && scoreInt <100) return 0;
//        if (scoreInt<90 && scoreInt>=80) return 1;
//        if (scoreInt<80) return 2;
//
//    }



    @Override
    public int getPartition(Text score, Text text2, int i) {
        int scoreInt = Integer.parseInt(score.toString());
        int a = 3;
        if (scoreInt>=90 && scoreInt <100) {a=0;}
        if (scoreInt<90 && scoreInt>=80) {a=1;}
        if (scoreInt<80) {a=2;}
        return a;
    }
}
package com.doit.scorep;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class Score {

    // 1 70
    // 2 74
    // 3 65
    // 4 80
    // 5 98
    // 6 94
    // 7 99
    // 8 75
    public static class ScoreMap extends Mapper<LongWritable, Text,Text,Text>{
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

            String[] split = value.toString().split(" ");
            String id = split[0];
            String score = split[1];
            context.write(new Text(score), new Text(id));
        }
    }

    public static class ScoreReducer extends Reducer<Text,Text,Text,IntWritable>{
        TreeMap<Integer, Text> treeMap;
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            treeMap  = new TreeMap<Integer, Text>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1.compareTo(o2);
                }
            });
            System.out.println("-------------------se******&&&&&tup----------");
        }

        @Override
        protected void reduce(Text score, Iterable<Text> id, Context context) throws IOException, InterruptedException {

           // treeMap.put(Integer.parseInt(score.toString()), id.iterator().next());
            Text ids = id.iterator().next();
            String scores = score.toString();
            treeMap.put(Integer.parseInt(scores),ids);
        }

        @Override
        protected void cleanup(Context context) throws IOException, InterruptedException {
            Iterator<Map.Entry<Integer, Text>> iterator = treeMap.entrySet().iterator();
           while (iterator.hasNext()){
               Map.Entry<Integer, Text> entry = iterator.next();
               Integer score = entry.getKey();
               Text id = entry.getValue();
               context.write(id,new IntWritable(score));
           }
            System.out.println("------------------clea******&&&&&&&nup---------");
        }
    }

    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        job.setJarByClass(Score.class);
        job.setNumReduceTasks(3);
        job.setPartitionerClass(ScorePartitioner.class);

        job.setMapperClass(ScoreMap.class);
        job.setReducerClass(ScoreReducer.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.setInputPaths(job, new Path("E:\\mrtest\\scores\\input"));
        Path outPath = new Path("E:\\mrtest\\scores\\output");
        FileSystem fileSystem = FileSystem.get(conf);
        if(fileSystem.exists(outPath)){
            fileSystem.delete(outPath, true);
        }

        FileOutputFormat.setOutputPath(job, outPath);

        boolean b = job.waitForCompletion(true);
        System.exit(b?0:1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值