查询语法
1 |
[WITH CommonTableExpression (, CommonTableExpression)*] (Note: Only available |
基本查询
1 |
select … from |
全表查询
1 |
select * from emp; |
条件查询
1 |
select empno, ename from emp; |
注意:
- SQL 语言大小写不敏感。
- SQL 可以写在一行或者多行
- 关键字不能被缩写也不能分行
- 各子句一般要分行写。
- 使用缩进提高语句的可读性。
列别名
- 重命名一个列
- 便于计算
- 紧跟列名,也可以在列名和别名之间加入关键字‘AS’
1 |
--询名称和部门 |
算术运算符
运算符 | 描述 | |
---|---|---|
A+B | A和B 相加 | |
A-B | A减去B | |
A*B | A和B 相乘 | |
A/B | A除以B | |
A%B | A对B取余 | |
A&B | A和B按位取与 | |
A\ | B | A和B按位取或 |
A^B | A和B按位取异或 | |
~A | A按位取反 |
1 |
--薪水加100后的信息 |
常用函数
1 |
--求总行数(count) |
Where语句
1.使用WHERE子句,将不满足条件的行过滤掉
2.WHERE子句紧随FROM子句
1 |
--查询出薪水大于1000的所有员工 |
比较运算符
操作符 | 支持的数据类型 | 描述 |
---|---|---|
A=B | 基本数据类型 | 如果A等于B则返回TRUE,反之返回FALSE |
A<=>B | 基本数据类型 | 如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL |
A<>B, A!=B | 基本数据类型 | A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE |
A<B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE |
A<=B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE |
A>B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE |
A>=B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE |
A [NOT] BETWEEN B AND C | 基本数据类型 | 如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果。 |
A IS NULL | 所有数据类型 | 如果A等于NULL,则返回TRUE,反之返回FALSE |
A IS NOT NULL | 所有数据类型 | 如果A不等于NULL,则返回TRUE,反之返回FALSE |
IN(数值1, 数值2) | 所有数据类型 | 使用 IN运算显示列表中的值 |
A [NOT] LIKE B | STRING 类型 | B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。 |
A RLIKE B, A REGEXP B | STRING 类型 | B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
1 |
--查询出薪水等于5000的所有员工 |
Like和RLike
- 使用LIKE运算选择类似的值
- 选择条件可以包含字符或数字:% 代表零个或多个字符(任意个字符)。_ 代表一个字符。
- RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
1 |
-- 查找以2开头薪水的员工信息 |
逻辑运算符
操作符 | 含义 |
---|---|
AND | 逻辑并 |
OR | 逻辑或 |
NOT | 逻辑否 |
1 |
--求每个部门的平均工资 |
Join语句
等值Join
注意:Hive支持通常的SQL JOIN语句,但
只支持等值连接,不支持非等值连接
。
1 |
--根据员工表和部门表中的部门编号相等,查询员工编号、员工名称和部门名称; |
表的别名:(1)使用别名可以简化查询。(2)使用表名前缀可以提高执行效率。
左外连接
左外连接:JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
1 |
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno = d.deptno; |
右外连接
右外连接:JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。
1 |
select e.empno, e.ename, d.deptno from emp e right join dept d on e.deptno = d.deptno; |
满外连接
满外连接:将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
1 |
select e.empno, e.ename, d.deptno from emp e full join dept d on e.deptno = d.deptno; |
多表连接
数据准备
1 |
[hadoop@datanode1 datas]$ vim location.txt |
创建位置表
1 |
create table if not exists default.location( |
导入数据
1 |
load data local inpath '/opt/module/datas/location.txt' into table default.location; |
多表连接查询
1 |
SELECT e.ename, d.deptno, l. loc_name |
注意:大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先启动一个MapReduce job对表e和表d进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表l;进行连接操作。Hive总是按照从左到右的顺序执行的。因此不是Hive总是按照从左到右的顺序执行的。
笛卡尔积
笛卡尔集会在下面条件下产生:
- 省略连接条件
- 连接条件无效
- 所有表中的所有行互相连接
1 |
--案例实操 |
排序
全局排序
Order By:全局排序,一个Reducer
1.使用 ORDER BY 子句排序
ASC(ascend): 升序(默认)
DESC(descend): 降序
ORDER BY 子句在SELECT语句的结尾
1 |
--查询员工信息按工资升序排列 |
按照别名排序
1 |
--按照员工薪水的2倍排序 |
MR内部排序(Sort By)
Sort By:每个Reducer内部进行排序,对全局结果集来说不是排序。
1 |
--设置reduce个数 |
分区排序 (Distribute By)
Distribute By:类似MR中partition,进行分区,结合sort by使用。
注意:Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
案例实操:
1 |
--需求:先按照部门编号分区,再按照员工编号降序排序。 |
Cluster By
当distribute by和sorts by字段相同时,可以使用cluster by方式。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒序排序,不能指定排序规则为ASC或者DESC。
1 |
select * from emp cluster by deptno; |
桶表
分区针对的是数据的存储路径;分桶针对的是数据文件。
分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是之前所提到过的要确定合适的划分大小这个疑虑。 分桶是将数据集分解成更容易管理的若干部分的另一个技术。
1 |
--创建分桶表 |
查看创建的分桶表
1 |
--创建分桶表时,数据通过子查询的方式导入 |
1 |
--为什么没有分桶呢 这里需要我们开启一个属性 |
1 |
--查询分桶的数据 |
分桶抽样查询
对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。
查询表stu_buck中的数据 select * from 表名 tablesample(bucket x out of y on id);
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据。
x表示从哪个bucket开始抽取,如果需要取多个分区,以后的分区号为当前分区号加上y。例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第4(x+y)个bucket的数据。
1 |
--抽取第一个分区的数据 |
其他常用查询函数
空字段赋值
NVL:给值为NULL的数据赋值,它的格式是NVL( string1,replace_with)。它的功能是如果string1为NULL,则NVL函数返回replace_with的值,否则返回string1的值,如果两个参数都为NULL ,则返回NULL。
1 |
--NULL用'无'代替 |
CASE WHEN
1 |
--数据准备 |
行转列
CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
1 |
##需求:把星座和血型一样的人归类到一起 |
列转行
EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。
LATERAL VIEW用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
1 |
--准备数据 |
窗口函数
函数 | 功能 |
---|---|
OVER() | 指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化 |
CURRENT ROW | 当前行 |
n PRECEDING | 往前n行数据 |
n FOLLOWING | 往后n行数据 |
UNBOUNDED | 起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点 |
LAG(col,n) | 往前第n行数据 |
LEAD(col,n) | 往后第n行数据 |
NTILE(n) | 把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始:n必须为int类型。 |
1 |
--准备数据 |
Rank
函数 | 功能 |
---|---|
RANK() | 排序相同时会重复,总数不会变 |
DENSE_RANK() | 排序相同时会重复,总数会减少 |
ROW_NUMBER() | 会根据顺序计算 |
1 |
--数据准备 |
自定义函数
Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展。
当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。
根据用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function) 一进一出
(2)UDAF(User-Defined Aggregation Function) 聚集函数,多进一出 类似于:count/max/min
(3)UDTF(User-Defined Table-Generating Functions) 一进多出 如lateral view explore()
编程步骤:
(1)继承org.apache.hadoop.hive.ql.UDF
(2)需要实现evaluate函数;evaluate函数支持重载;
(3)在hive的命令行窗口创建函数
1 |
# 添加jar |
自定义UDF函数
1 |
<dependencies> |
java类
1 |
import org.apache.hadoop.hive.ql.exec.UDF; |
上传上服务器
添加jar
1 |
hive> add jar /home/hadoop/udf.jar; |