分桶表:
感觉没怎么用到,有兴趣自己查下
修改表结构
[重命名:]()
alter table old_table_name rename to new_table_name;
把表score4修改成score5
```sql
alter table score4 rename to score5;
```
- 查询表结构
```sql
desc score5;
```
- 添加列
```sql
alter table score5 add columns (mycol string, mysco int);
```
- 更新列
```sql
alter table score5 change column mysco mysconew int;
```
+ 删除表
```sql
drop table score5;
```
查询语法:
创建跟删除这些事应该都轮不到你,你能做的就是查询==
SELECT
```sql
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
```
1. order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
2. sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
3. distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
4. cluster by(字段) 除了具有distribute by的功能外,还会对该字段进行排序.
因此,如果distribute 和sort字段是同一个时,此时,`cluster by = distribute by + sort by`
[全表查询]()
```sql
select * from score;
```
select s_id ,c_id from score;
[列别名]()
1)重命名一个列。
2)便于计算。
3)紧跟列名,也可以在列名和别名之间加入关键字‘AS’
```sql
select s_id as myid ,c_id from score;
```
常用函数
建议:学习的时候使用本地模式,不然等太久了
set hive.exec.mode.local.auto=true;
- 求总行数(count)
```sql
select count(1) from score;
```
- 求分数的最大值(max)
```sql
select max(s_score) from score;
```
- 求分数的最小值(min)
```sql
select min(s_score) from score;
```
- 求分数的总和(sum)
```sql
select sum(s_score) from score;
```
- 求分数的平均值(avg)
```sql
select avg(s_score) from score;
```
### 4.4. LIMIT语句
典型的查询会返回多行数据。LIMIT子句用于限制返回的行数。
```sql
select * from score limit 3;
```
### 4.5. WHERE语句
1. 使用WHERE 子句,将不满足条件的行过滤掉。
2. WHERE 子句紧随 FROM 子句。
3. 案例实操
查询出分数大于60的数据
```sql
select * from score where s_score > 60;
[比较运算符]():不用刻意记,用多了就好
- 查询分数等于80的所有的数据
```sql
select * from score where s_score = 80;
```
- 查询分数在80到100的所有数据
```sql
select * from score where s_score between 80 and 100;
```
- 查询成绩为空的所有数据
```sql
select * from score where s_score is null;
```
- 查询成绩是80和90的数据
```sql
select * from score where s_score in(80,90);
### 4.6. LIKE 和 RLIKE
1. 使用LIKE运算选择类似的值
2. 选择条件可以包含字符或数字:
```text
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
```
1. RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
2. 案例实操
1. 查找以8开头的所有成绩
```sql
select * from score where s_score like '8%';
```
1. 查找第二个数值为9的所有成绩数据
```sql
select * from score where s_score like '_9%';
```
1. 查找s_id中含1的数据
```sql
select * from score where s_id rlike '[1]'; # like '%1%'
4.7. 逻辑运算符
- 查询成绩大于80,并且s_id是01的数据
```sql
select * from score where s_score >80 and s_id = '01';
```
- 查询成绩大于80,或者s_id 是01的数
```sql
select * from score where s_score > 80 or s_id = '01';
```
- 查询s_id 不是 01和02的学生
```sql
select * from score where s_id not in ('01','02');
```
分组
#### GROUP BY 语句
GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
案例实操:
- 计算每个学生的平均分数
```sql
select s_id ,avg(s_score) from score group by s_id;
```
- 计算每个学生最高成绩
```sql
select s_id ,max(s_score) from score group by s_id;
```
#### HAVING 语句
1. having与where不同点
1. where针对表中的列发挥作用,查询数据;having针对查询结果中的列发挥作用,筛选数据。
2. where后面不能写分组函数,而having后面可以使用分组函数。
3. having只用于group by分组统计语句。
2. 案例实操:
- 求每个学生的平均分数
```sql
select s_id ,avg(s_score) from score group by s_id;
```
- 求每个学生平均分数大于85的人
```sql
select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
```
JOIN 语句
Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。
案例操作: 查询分数对应的姓名
```sql
select s.s_id,s.s_score,stu.s_name,stu.s_birth from score s join student stu on s.s_id = stu.s_id;
``
#### 4.9.2. 表的别名
- 好处
- 使用别名可以简化查询。
- 使用表名前缀可以提高执行效率。
- 案例实操
- 合并老师与课程表
```sql
select * from techer t join course c on t.t_id = c.t_id;
```
#### 4.9.3. 内连接
内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。
```sql
select * from techer t inner join course c on t.t_id = c.t_id;
```
#### 4.9.4. 左外连接
左外连接:JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
查询老师对应的课程
```sql
select * from techer t left join course c on t.t_id = c.t_id;
```
#### 4.9.5. 右外连接
右外连接:JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。
```sql
select * from teacher t right join course c on t.t_id = c.t_id;
```
#### 4.9.6. 多表连接
注意:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
多表连接查询,查询老师对应的课程,以及对应的分数,对应的学生
```sql
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对表techer和表course进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表score;进行连接操作。
全局排序
Order By:全局排序,一个reduce
1. 使用 ORDER BY 子句排序
ASC(ascend): 升序(默认)
DESC(descend): 降序
2. ORDER BY 子句在SELECT语句的结尾。
3. 案例实操
1. 查询学生的成绩,并按照分数降序排列
```sql
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
```
1. 查询学生的成绩,并按照分数升序排列
```sql
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score asc;
```
#### 4.10.2. 按照别名排序
按照分数的平均值排序
```sql
select s_id ,avg(s_score) avg from score group by s_id order by avg;
```
#### 4.10.3. 多个列排序
按照学生id和平均成绩进行排序
```sql
select s_id ,avg(s_score) avg from score group by s_id order by s_id,avg;
```
#### 4.10.4. 每个MapReduce内部排序(Sort By)局部排序
Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。
1. 设置reduce个数
```sql
set mapreduce.job.reduces=3;
```
1. 查看设置reduce个数
```sql
set mapreduce.job.reduces;
```
1. 查询成绩按照成绩降序排列
```sql
select * from score sort by s_score;
```
1. 将查询结果导入到文件中(按照成绩降序排列)
```sql
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score;
```
#### 4.10.5. 分区排序(DISTRIBUTE BY)
Distribute By:类似MR中partition,进行分区,结合sort by使用。
注意,Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。
对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
案例实操:先按照学生id进行分区,再按照学生成绩进行排序。
1. 设置reduce的个数,将我们对应的s_id划分到对应的reduce当中去
```sql
set mapreduce.job.reduces=7;
```
1. 通过distribute by 进行数据的分区
```sql
insert overwrite local directory '/home/hadoop/data/sort' select * from score distribute by s_id sort by s_score;
```
#### 4.10.6. CLUSTER BY
当distribute by和sort by字段相同时,可以使用cluster by方式。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒序排序,不能指定排序规则为ASC或者DESC。
以下两种写法等价
```sql
select * from score cluster by s_id;
select * from score distribute by s_id sort by s_id;
窗口函数:
over()
重点! 我不是特别会
1、over()窗口函数的语法结构
分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置)
over()函数中包括三个函数:包括分区partition by 列名、排序order by 列名、指定窗口范围rows between 开始位置 and 结束位置。我们在使用over()窗口函数时,over()函数中的这三个函数可组合使用也可以不使用。
over()函数中如果不使用这三个函数,窗口大小是针对查询产生的所有数据,如果指定了分区,窗口大小是针对每个分区的数据。
找到的有关28道题:链接出处:
https://www.jianshu.com/p/3f3cf58472ca
1、使用 over() 函数进行数据统计, 统计每个用户及表中数据的总数
2、求用户明细并统计每天的用户总数
3、计算从第一天到现在的所有 score 大于80分的用户总数
4、计算每个用户到当前日期分数大于80的天数
vi test_window.txt
20191020,11111,85
20191020,22222,83
20191020,33333,86
20191021,11111,87
20191021,22222,65
20191021,33333,98
20191022,11111,67
20191022,22222,34
20191022,33333,88
20191023,11111,99
20191023,22222,33
create table test_window
(logday string,
userid string,
score int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
#加载数据
load data local inpath '/home/hadoop/data/test_window.txt' into table test_window;
NOTE:
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:当前行
UNBOUNDED:起点(一般结合PRECEDING,FOLLOWING使用)
UNBOUNDED PRECEDING 表示该窗口最前面的行(起点)
UNBOUNDED FOLLOWING:表示该窗口最后面的行(终点)
比如说:
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(表示从起点到当前行)
ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING(表示往前2行到往后1行)
ROWS BETWEEN 2 PRECEDING AND 1 CURRENT ROW(表示往前2行到当前行)
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING(表示当前行到终点)
1、使用 over() 函数进行数据统计, 统计每个用户及表中数据的总数
select *, count(1) over() as total from test_window;
这里使用 over() 与 select count(*) 有相同的作用,好处就是,在需要计算总数时不用再进行一次关联。
2、求用户明细并统计每天的用户总数
可以使用 partition by 按日期列对数据进行分区处理,如:over(partition by logday)
select *, count(1) over(partition by logday) as day_total from test_window;
3、计算从第一天到现在的所有 score 大于80分的用户总数
select *,count(1)over(order by logday rows between unbounded preceding and current row)as total
from test_window
where score > 80;
4、计算每个用户到当前日期分数大于80的天数
select *,
count(1)over(partition by userid order by logday rows between unbounded preceding and current row) as total
from test_window
where score > 80 order by logday, userid;
第二套练习:
1、查询在2017年4月份购买过的顾客及总人数
2、查询顾客的购买明细及月购买总额
3、查询顾客的购买明细及到目前为止每个顾客购买总金额
4、查询顾客上次的购买时间----lag()over()偏移量分析函数的运用
5、查询前20%时间的订单信息
jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94
create table business
(
name string,
orderdate string,
cost int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
load data local inpath "/home/hadoop/data/business.txt" into table business;
1、查询在2017年4月份购买过的顾客及总人数
分析:按照日期过滤、分组count求总人数(分组为什么不是用group by?自己思考)
select *,count(1)over() as total from business
where substr(orderdate,1,7) = '2017-04';
2、查询顾客的购买明细及月购买总额
是计算每月每个用户的消费金额
select
*,
sum(cost) over(partition by name,substr(orderdate,1,7)) total_amount
from
business;
3、查询顾客的购买明细及到目前为止每个顾客购买总金额
分析:按照顾客分组、日期升序排序、组内每条数据将之前的金额累加
select
*,
sum(cost) over(partition by name order by orderdate
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) total_amount
from
business;
4、查询顾客上次的购买时间----lag()over()偏移量分析函数的运用
lag()over()偏移量分析函数的运用
select
name,
orderdate,
cost,
lag(orderdate,1) over(partition by name order by orderdate) last_date
from
business;
5、查询前20%时间的订单信息
select *
from
(select *,
ntile(5)over(order by cost)sortgroup_num from business)t
where t.sortgroup_num = 1;
第三套练习:
1、每门学科学生成绩排名(是否并列排名、空位排名三种实现)
2、每门学科成绩排名top n的学生
vi grade.txt
孙悟空 语文 87
孙悟空 数学 95
孙悟空 英语 68
大海 语文 94
大海 数学 56
大海 英语 84
宋宋 语文 64
宋宋 数学 86
宋宋 英语 84
婷婷 语文 65
婷婷 数学 85
婷婷 英语 78
create table grade
(
name string,
subject string,
score int
) row format delimited fields terminated by "\t";
#加载数据
load data local inpath '/home/hadoop/data/grade.txt' into table grade;
1、每门学科学生成绩排名(是否并列排名、空位排名三种实现)
select *,
row_number()over(partition by subject order by score desc),
rank()over(partition by subject order by score desc),
dense_rank()over(partition by subject order by score desc)
from grade;
2、每门学科成绩排名top n的学生
select
*
from
(
select
*,
row_number() over(partition by subject order by score desc) rmp
from grade
) t
where t.rmp<=1;
=================================================
接着练习别的
创建部门表
create external table if not exists guigu.dept( deptno int,
dname string,
loc int
)
row format delimited fields terminated by '\t';
创建员工表
create external table if not exists guigu.emp( empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
row format delimited fields terminated by '\t';
load data local inpath '/home/hadoop/data/dept.txt' into table guigu.dept;
load data local inpath '/home/hadoop/data/emp.txt' into table guigu.emp;
create table dept_partition( deptno int, dname string, loc string
)
partitioned by (month string)
row format delimited fields terminated by '\t';
load data local inpath '/home/hadoop/data/dept.txt' into table guigu.dept_partition partition(month='201709');
load data local inpath '/home/hadoop/data/dept.txt' into table guigu.dept_partition partition(month='201708');
load data local inpath '/home/hadoop/data/dept.txt' into table guigu.dept_partition partition(month='201707');
跟前面的基础操作类似:
select count(*) cnt from emp;
select max(sal) max_sal from emp;
select min(sal) min_sal from emp;
select sum(sal) sum_sal from emp;
select avg(sal) avg_sal from emp;
Group By 语句
计算 emp 表每个部门的平均工资
select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno;
计算 emp 每个部门中每个岗位的最高薪水
select t.deptno, t.job, max(t.sal) max_sal from emp t group by
t.deptno, t.job;
2.案例实操 (1)求每个部门的平均薪水大于 2000 的部门
求每个部门的平均工资
select deptno, avg(sal) from emp group by deptno;
求每个部门的平均薪水大于 2000 的部门
select deptno, avg(sal) avg_sal from emp group by deptno having
avg_sal > 2000;
根据员工表和部门表中的部门编号相等,查询员工编号、员工名称和部门名称
select e.empno, e.ename, d.deptno, d.dname from emp e join dept d
on e.deptno = d.deptno;
合并员工表和部门表
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno
= d.deptno;
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno
= d.deptno order by d.deptno;
左外连接
左外连接:JOIN 操作符左边表中符合 WHERE 子句的所有记录将会被返回。
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno = d.deptno;
vi location.txt
1700 Beijing
1800 London
1900 Tokyo
create table if not exists guigu.location( loc int,
loc_name string
)
row format delimited fields terminated by '\t';
load data local inpath '/home/hadoop/data/location.txt' into table guigu.location;
SELECT e.ename, d.dname, l.loc_name
FROM emp e
JOIN dept d
ON d.deptno = e.deptno
JOIN location l
ON d.loc = l.loc;
查询员工信息按工资升序排列
select * from emp order by sal;
查询员工信息按工资降序排列
select * from emp order by sal desc;
select ename, sal*2 twosal from emp order by twosal;
select ename, deptno, sal from emp order by deptno, sal ;
vi emp_sex.txt
悟空 A 男
大海 A 男
宋宋 B 男
凤姐 A 女
婷姐 B 女
婷婷 B 女
create table emp_sex(
name string,
dept_id string,
sex string)
row format delimited fields terminated by "\t";
load data local inpath '/home/hadoop/data/emp_sex.txt' into table emp_sex;
select
dept_id,
sum(case sex when '男' then 1 else 0 end) male_count,
sum(case sex when '女' then 1 else 0 end) female_count
from
emp_sex
group by
dept_id;
vi movie.txt
《疑犯追踪》 悬疑,动作,科幻,剧情
《Lie to me》 悬疑,警匪,动作,心理,剧情
《战狼2》 战争,动作,灾难
create table movie_info(
movie string,
category array
row format delimited fields terminated by "\t"
collection items terminated by ",";
load data local inpath "/home/hadoop/data/movie.txt" into table movie_info;
select
movie,
category_name
from
movie_info lateral view explode(category) table_tmp as category_name;
把上面的business.txt 数据再用一次
load data local inpath "/home/hadoop/data/business.txt" into table business;
(1)查询在2017年4月份购买过的顾客及总人数
select name,count(*) over ()
from business
where substring(orderdate,1,7) = '2017-04'
group by name;
(2)查询顾客的购买明细及月购买总额
select name,orderdate,cost,sum(cost) over(partition by month(orderdate)) from
business;
(4)查看顾客上次的购买时间
select name,orderdate,cost,
lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as time1, lag(orderdate,2) over (partition by name order by orderdate) as time2
from business;
(5)查询前20%时间的订单信息
select * from (
select name,orderdate,cost, ntile(5) over(order by orderdate) sorted
from business
) t
where sorted = 1;
vi score.txt
孙悟空 语文 87
孙悟空 数学 95
孙悟空 英语 68
大海 语文 94
大海 数学 56
大海 英语 84
宋宋 语文 64
宋宋 数学 86
宋宋 英语 84
婷婷 语文 65
婷婷 数学 85
婷婷 英语 78
create table score(
name string,
subject string,
score int)
row format delimited fields terminated by "\t";
load data local inpath '/home/hadoop/data/score.txt' into table score;
select name,
subject,
score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from score;