文章目录

  • 1 基本查询
  • 2 排序
  • 2.1 全局排序(Order By)
  • 2.2 局部排序 Sort By 区内有序
  • 2.3 Distribute By 分区(为Sort by 指定分区)
  • 2.4 Cluster By 排序
  • 4 常用查询函数
  • 4.1 NVL 空字段赋值
  • 4.2 CASE WHEN 语句
  • 4.3 IF 语句
  • 4.4 行转列
  • 4.5 列转行
  • 4.6 时间处理
  • 5 自定义函数UDF


基本语句语法

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list 
`	| [DISTRIBUTE BY col_list] [SORT BY col_list]
  ]
[LIMIT number]

创建数据

(1)创建部门表

create table if not exists dept( 
	deptno int,
	dname string, loc int
)
row format delimited fields terminated by '\t';


hive 排序空值 hive的排序_hive 排序空值

(2)创建员工表

create table if not exists emp( 
	empno int,
	ename string, 
	job string, 
	mgr int,
	hiredate string, 
	sal double,
	comm double, 
	deptno int
)
row format delimited fields terminated by '\t';


hive 排序空值 hive的排序_字段_02

(3)导入数据(使用load加载)

从本地HDFS导入数据

load data local inpath '/opt/module/datas/dept.txt' into table dept;
load data local inpath '/opt/module/datas/emp.txt' into table emp;

1 基本查询

(1)SQL 语言大小写不敏感。
(2)SQL 可以写在一行或者多行
(3)关键字不能被缩写也不能分行
(4)各子句一般要分行写。
(5)使用缩进提高语句的可读性。

1.全表查询

hive (default)> select * from emp;
hive (default)> select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp ;

2.选择特定列查询

hive (default)> select empno, ename from emp;

3.列别名(关键字‘AS’)

hive (default)> select ename AS name, deptno dn from emp;

4.算术运算符

hive 排序空值 hive的排序_hive_03

hive (default)> select sal +1 from emp;

5.常用函数

计数 count(*)、最大值(max)、最小值(min)、总和(sum)、平均值(avg

select count(*) cnt 
from emp;
select avg(sal) avg_sal 
from emp;

6.Limit语句

Limit语句用于限制返回的行数

select * from emp limit 3;

7. Where语句

Where语句用于过滤

select * from emp where sal >1000;

注意:where 子句中不能使用字段别名。

8.比较运算符(Between/In/ Is Null)

9.Like 和 Rlike

like: 选择类似的值

% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。

Rlike子句是 Hive 中这个功能的一个扩展,其可以通过 Java 的正则表达式这个更强大 的语言来指定匹配条件。

10.逻辑运算符(And/Or/Not)

11.Group By语句

12.Having语句

13.Join语句

Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。

内连接 join
左外连接 left join
右外连接 right join
满外连接(全连接) full join
多表连接

hive (default)>SELECT e.ename, d.deptno, l. loc_name
FROM   emp e 
JOIN   dept d
ON     d.deptno = e.deptno 
JOIN   location l
ON     d.loc = l.loc;

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


笛卡尔积

hive 排序空值 hive的排序_字段_04


2 排序

2.1 全局排序(Order By)

Order By:全局排序,一个Reducer

对查询结果做全局排序,所有的数据都通过一个reduce进行处理的过程,对于大数据集,这个过程将消耗很大的时间来执行。默认是asc升序

hive (default)> select * from emp order by sal; 
hive (default)> select * from emp order by sal desc;


hive 排序空值 hive的排序_hive_05

2.2 局部排序 Sort By 区内有序

Sort By:对于大规模的数据集 order by 的效率非常低。在很多情况下,并不需要全局排 序,此时可以使用 sort by。

Sort by 为每个 reducer 产生一个排序文件。每个 Reducer 内部进行排序,对全局结果集 来说不是排序。

每个MapReduce内部排序

  • 对每个Reducer进行排序,不影响全局结果集
  • 直接使用会将结果平均分配给每个文件(避免数据倾斜)
  • 一般配合Distribute By使用

设置 reduce 个数

hive (default)> set mapreduce.job.reduces=3;

查看设置 reduce 个数

hive (default)> set mapreduce.job.reduces;

根据部门编号降序查看员工信息

hive (default)> select * from emp sort by deptno desc;

hive 排序空值 hive的排序_hive 排序空值_06

hive 排序空值 hive的排序_hive 排序空值_07


注:如果没有指定分区规则,则随机分区分配数据

hive 排序空值 hive的排序_hive 排序空值_08

将查询结果导入到文件中(按照部门编号降序排序)

hive 排序空值 hive的排序_字段_09


hive 排序空值 hive的排序_hive 排序空值_10

sort by:是在每个reduce内部进行排序,是执行一个局部排序过程,可以保证每个reduce的输出数据都是有序的(但并非全局有效),能够提高后面进行的全局排序的效率。默认是asc升序
例如:select * from table sort by salary desc;

注:使用sort by需要预先设置Reduce的数量大于1,这样才会做局部排序,如果Reduce数量是1,作用与order by一样,全局排序。


2.3 Distribute By 分区(为Sort by 指定分区)

Distribute By: 在有些情况下,我们需要控制某个特定行应该到哪个 reducer,通常是为了进行后续的聚集操作。

distribute by 子句可以做这件事。

distribute by 类似MapReduce中的Partition分区(自定义分区),一般配合Sort By排序使用

对于 distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到 distribute by 的效果。

注意:该语句需要写在 Sort By 语句之前!

按deptno分4个区,按照 sal 排序

hive 排序空值 hive的排序_hive 排序空值_11

-- 先设置reduce的个数
set mapreduce.job.reduces=3;
-- 先按照id值分区,再按照age值升序排序
insert overwrite local directory '/opt/datas/dis-out'
select * from student distribute by id sort by age;

2.4 Cluster By 排序

当 Distribute By 和 Sort By 字段相同时,可以使用 Cluster By 方式

该排序只能是升序排序

-- 以下两种写法等价
select * from student cluster by grade;
select * from student distribute by grade sort by grade;

4 常用查询函数

4.1 NVL 空字段赋值

NVL:给值为NULL的数据赋值

格式:NVL( string1, replace_with)

如果string1为NULL,则返回replace_with的值,否则返回string1的值,如果两个参数都为NULL ,则返回NULL。

-- 如果age为null,用18代替
select nvl(age,18) from student;

-- 替换的参数可以是字段,如果age为null,用id值代替
select nvl(age,id) from student;

4.2 CASE WHEN 语句

需求

求出不同部门男女各多少人

hive 排序空值 hive的排序_hive 排序空值_12

结果

部门    男      女
A       2       1
B       1       2
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;

4.3 IF 语句

-- 以下代码等价于上面的case when
select
dept_id,
sum(if(gender='男',1,0)) male_count,
sum(if(gender='女',1,0)) female_count
from emp_sex 
group by dept_id;

4.4 行转列

行转列:将多个列中的数据在一列中输出
列转行:将一列中的数据拆分成多行

Concat

concat(string1/col, string2/col, …)

输入任意个字符串(或字段,可以为int类型等),返回拼接后的结果

select concat(id,'-',name,'-',age) 
from student;

Concat_ws

concat_ws(separator, str1, str2, …)

特殊形式的 concat(),参数只能为字符串,第一个参数为后面参数的分隔符

分隔符可以是与后面参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;

select concat_ws('-', name, gender) 
from student;

Collect_set(聚合,返回数组类型)

collect_set(col)

将某字段进行去重处理返回array类型;该函数只接受基本数据类型

select collect_set(age) 
from student;

collect_set
collect_list,区别就是set去重,list不去重


需求

把星座和血型一样的人归类到一起

hive 排序空值 hive的排序_数据_13


结果

射手座,A            大海|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋
select
    t1.base,
    concat_ws('|', collect_set(t1.name)) as name
from
    (select name,concat(constellation, ",", blood_type) as base
    from person_info) as t1
group by
    t1.base;

需求2

hive 排序空值 hive的排序_hive_14


结果:

张三    语文,数学,英语   98,95,89
李四    语文,数学,英语   97,88,90
select 
	stu_name,
	concat_ws(',',collect_set(course)) as course,
	concat_ws(',',collect_set(score)) as score
from student
group by stu_name

4.5 列转行

行转列:将多个列中的数据在一列中输出
列转行:将一列中的数据拆分成多行

Explode

explode(col)

将hive一列中复杂的 array 或 map 结构拆分成多行

-- 将上面collect_set后的结果使用explode拆分
select explode(ages)
from (
	select collect_set(age) as ages 
	from student ) as n1;

Lateral View

LATERAL VIEW udtf(expression) tableAlias AS columnAlias

配合 split, explode 等UDTF一起使用,它能够将一列数据拆成多行数据,并且对拆分后的结果进行聚合

需求

假设有如下movies表,字段名分别为movie(string)category(array<string>)

hive 排序空值 hive的排序_数据_15


转换为

hive 排序空值 hive的排序_数据_16

select movie,category_name
from  movies 
lateral view explode(category) table_tmp as category_name;

-- 结果:
--《疑犯追踪》	悬疑
--《疑犯追踪》	动作
--《疑犯追踪》	科幻
--《疑犯追踪》	剧情
--《海豹突击队》	动作
-- ...

需求2

a       b       1,2,3
c       d       4,5,6

转换为

a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
select col1, col2, col5
from test
lateral  view explode(split(col3,','))  b AS col5

4.6 时间处理

Date_format

格式化时间 ,注意:只能匹配横杆 “-”

select date_format('2021-02-23','yyyy-MM-dd HH:mm:ss');
//结果: 2021-02-23 00:00:00

Date_add

时间跟天数相加,天数可以为负

select date_add('2021-02-13', 10); 
//结果: 2021-02-23

Date_sub

时间跟天数相减,天数可以为负

select date_sub('2021-02-23', 10);
//结果: 2021-02-13

Datediff

两个时间相减,结果为天数,注意:是参数1 - 参数2

时分秒不影响最后的结果

select datediff('2021-02-13', '2021-02-23');
//结果: -10
select datediff('2021-02-23', '2021-02-13');
//结果: 10
select datediff('2021-02-23 11:27:21','2021-02-13 17:15:12');
//结果: 10

5 自定义函数UDF

1)Hive 自带了一些函数,比如:max/min 等,但是数量有限,自己可以通过自定义 UDF 来方便的扩展。

2)当 Hive 提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。

3)根据用户自定义函数类别分为以下三种:

  • UDF(User-Defined-Function) 一进一出
  • UDAF(User-Defined Aggregation Function) 聚集函数,多进一出 类似于:count/max/min
  • UDTF(User-Defined Table-Generating Functions) 一进多出
    如 lateral view explode()

4)编程步骤:

  1. 继承 Hive 提供的类
org.apache.hadoop.hive.ql.udf.generic.GenericUDF 
org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
  1. 实现类中的抽象方法
  2. 在 hive 的命令行窗口创建函数添加 jar
add jar linux_jar_path

创建 function

create [temporary] function [dbname.]function_name AS class_name;
  1. 在 hive 的命令行窗口删除函数
drop [temporary] function [if exists] [dbname.]function_name;