好程序员大数据学习路线之hive表的查询

185 篇文章 3 订阅
5 篇文章 0 订阅

  1.join 查询

  1、永远是小结果集驱动大结果集(小表驱动大表,小表放在左表)。 2、尽量不要使用join,但是join是难以避免的。

  left join 、 left outer join 、 left semi join(左半开连接,只显示左表信息)

  hive在0.8版本以后开始支持left join

  left join 和 left outer join 效果差不多

  hive的join中的on只能跟等值连接 "=",不能跟< >= <= !=

  join:不加where过滤,叫笛卡尔积

  inner join : 内连接

  outer join :外链接

  full outer join : 全外连接,寻找表中所有满足连接(包括where过滤)。

  ##创建学生测试表
CREATE  TABLE  student (
id  INT,
name   string,
sex  string,
birth  string,
department  string,
address  string 
)
row format delimited fields terminated by ','
;
##从本地加载数据
load data local inpath '/root/Desktop/student.txt' into table student;
##创建学生成绩测试表
CREATE  TABLE  score (
stu_id  INT,
c_name  string,
grade  string
)
row format delimited fields terminated by ','
;
##从hdfs加载数据
load data  inpath '/hive.data/score.txt' into table score;
##创建学生基本信息测试表
create table stuinfo(
id int,
height double,
weight double
)
row format delimited fields terminated by ','
;
##从本地加载数据
load data local inpath '/root/Desktop/stuinfo.txt' into table stuinfo;

  1.1 左连接

  如果左边有数据,右边没有数据,则左边有数据的记录的对应列返回为空。

  ##使用左连接查询:student表为驱动表,通过id连接
select 
student.name,
score.c_name,
score.grade 
from student 
left join score 
on student.id = score.stu_id
;

  1.2 左外连接

  如果左边有数据,右边没有数据,则左边有数据的记录的对应列返回为空。

  ##使用左外连接查询:student表为驱动表,通过id连接
select 
student.name,
score.c_name,
score.grade 
from student 
left outer join score 
on student.id = score.stu_id
;

  1.3 左半连接

  left semi join是left join 的一种优化,并且通常用于解决exists in,写left semi join 查询时必须遵循一个限制:右表(sales) 只能在 on子句中出现,且不能在select 表达式中引用右表。

  ##左半连接
select 
student.* 
from student 
left semi join score on 
student.id=score.id
;
##查询结果等价于
select * from student where student.id not in (select stu_id from score);

  1.4 右外连接

  right outer join和right join差不多,不常用

  如果左边没有数据,右边有数据,则右边有数据的记录对应列返回为空。

  ##使用右外连接查询:score表为驱动表,通过id连接
select 
student.name,
score.c_name,
score.grade 
from student 
right outer join score 
on student.id = score.stu_id
;

  1.5 全外连接

  ##全外连接
select 
student.name,
score.c_name,
score.grade 
from student 
full outer join score 
on student.id = score.stu_id
;

  ##不使用join,from 后面跟多个表名使用","分割 、 inner join 、join :三种效果一样
select 
student.name,
score.c_name,
score.grade 
from student,score 
where 
student.id = score.stu_id
;

  1.6 内连接

  ##使用内连接查询所有有考试成绩的学生的学生姓名,学科名,学科成绩,及身高
select 
student.name,
score.c_name,
score.grade, 
stuinfo.height
from student 
inner join score 
on student.id = score.stu_id
join stuinfo
on student.id = stuinfo.id
;

  1.7 hive提供一个小表标识,是hive提供的一种优化机制

  ##小表标识:/*+STREAMTABLE(表名)*/
select
/*+STREAMTABLE(score)*/
student.name,
score.c_name,
score.grade, 
stuinfo.height
from student 
inner join score 
on student.id = score.stu_id
join stuinfo
on student.id = stuinfo.id
;

  1.8 map-side join:

  如果有一个连接表小到足以放入内存, Hive就可以把较小的表放入每个mapper的内存来执行连接操作。这就叫做map连接。当有一大一小表的时候,适合用map-join。会将小表文件缓存,放到内存中,在map端和内存中的数据一一进行匹配,连接查找关系。hive-1.2.1 默认已经开启map-side join:hive.auto.convert.join=true

  select 
student.name,
score.c_name,
score.grade, 
stuinfo.height
from student 
inner join score 
on student.id = score.stu_id
join stuinfo
on student.id = stuinfo.id
;

  hive 0.7版本以前,需要hive提供的mapjoin()标识。来标识该join为map-side join。标识已经过时,但是写上仍然识别

  select
/*+MAPJOIN(student)*/
student.name,
score.c_name,
score.grade, 
stuinfo.height
from student 
inner join score 
on student.id = score.stu_id
join stuinfo
on student.id = stuinfo.id
;

  hive怎么知道将多大文件缓存,配置文件中配置,下面为默认配置

  <property>
    <name>hive.mapjoin.smalltable.filesize</name>
    <value>25000000</value>
  </property>

  2.group by:

  GROUP BY 语句通常会和聚合函数一起使用,按照一个或者多个列对结果进行分组,然后对每个组执行聚合操作。使用group by后,查询的字段要么出现在聚合函数中,要么出现在group by 后面。

  ##查询学生的考试门数,及平均成绩
select 
count(*),
avg(grade)
from student join score
on student.id=score.stu_id
group by student.id;

  3.where

  SELECT语句用于选取字段,WHERE语句用于过滤条件,两者结合使用可以查找到符合过滤条件的记录。后面不能跟聚合函数或者聚合函数的结果,能跟普通的查询值或者是方法

  ##查询学生的考试平均成绩大于90分
select 
count(*),
avg(grade) avg_score
from student join score
on student.id=score.stu_id
where student.id<106
group by student.id
having avg_score>90;

  4.having:

  对查询出来的结果进行过滤,通常和group by搭配使用。

  ##查询学生的考试平均成绩大于90分的学生id及平均成绩
select 
count(*),
avg(grade) avg_score
from student join score
on student.id=score.stu_id
group by student.id
having avg_score>90;

  5.排序

  sort by :排序,局部排序,只能保证单个reducer的结果排序。 order by: 排序,全局排序。保证整个job的结果排序。 当reducer只有1个的时候,sort by 和 order by 效果一样。建议使用sort by 通常和: desc asc .(默认升序)

  ##查询学生平均成绩按照降序排序
select 
avg(grade) avg_score
from 
student join score
on student.id=score.stu_id
group by student.id
order by avg_score desc;

  设置reducer个数(等于1 或者 2):

  set mapreduce.job.reduces=2

  ##使用order by
select 
avg(grade) avg_score
from 
student join score
on student.id=score.stu_id
group by student.id
order by avg_score desc;
##使用sort by
select 
avg(grade) avg_score
from 
student join score
on student.id=score.stu_id
group by student.id
sort by avg_score desc;

  6.distribute by:

  控制map中如何输出到reduce。整个hive语句转换成job默认都有该过程,如果不写,默认使用第一列的hash值来分。当只有一个reducer的时候不能体现出来。如果distribute by和sort by 一起出现的时候注意顺序问题??distribute by在前面

  clusterd by : 它等价于distribute by和sort by(升序)。后面跟的字段名需要一样 clusterd by它既兼有distribute by,还兼有sort by (只能是升序)

  select 
id 
from
student
distribute by id
sort by id;

  select 
id 
from
student
clusterd by id;

  7.limit : 限制结果集的。

  select 
id,name
from student
limit 3;

  8.union all:

  将两个或者多个查询的结果集合并到一起,不去重每一个结果集排序。字段数必须一致,字段类型尽量相同

  ##将id<108的和id>103的使用union all合并
select
id sid,
name snames
from student
where id<108
union all
select
id sid,
name sname
from student
where id>103;

  9.union:

  将两个或者多个查询结果集合并到一起,去重,合并后的数据排序

  ##将id<108的和id>103的使用union合并
select
id sid,
name sname
from student
where id<108
union
select
id sid,
name sname
from student
where id>103
order by sname;

  10.子查询

  子查询是内嵌在另一个SQL 语句中的SELECT 语句。Hive 对子查询的支持很有限。它只允许子查询出现在SELECT 语句的FROM 子句中。Hive支持非相关子查询,这个子查询通过IN或EXISTS语法在WHERE子句中进行查询。Hive目前暂不支持相关子查询,相关子查询的执行依赖于外部查询的数据。

  ##非相关子查询
select 
id,name
from 
student
where id 
in
(select stu_id 
from 
score);

  ##相关子查询的执行依赖于外部查询的数据
select sid,uname
from 
(select 
 id sid,
 name uname
 from student
) s
order by sid
##外层查询像访问表那样访问子查询的结果,这是为什么必须为子查询赋予一个别名(s)的原因。子查询中的列必须有唯一的名称,以便外层查询可以引用这些列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值