查询
查询语法:
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]
基本查询
演示用表:
即 oracle 数据库自带的
scott演示表
create table if not exists dept(deptno int,dname string,loc string)row format delimitedfields terminated by ',';create table if not exists emp(empno int,ename string,job string,mgr int,hiredate string,sal double,comm double,deptno int)row format delimitedfields terminated by ',';
emp表数据:
7369,SMITH,CLERK,7902,1980-12-17,800,,207499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,307521,WARD,SALESMAN,7698,1981-02-22,1250,500,307566,JONES,MANAGER,7839,1981-04-02,2975,,207654,MARTIN,SALESMAN,7698,1981-09-28,1250,1400,307698,BLAKE,MANAGER,7839,1981-05-01,2850,,307782,CLARK,MANAGER,7839,1981-06-09,2450,,107788,SCOTT,ANALYST,7566,1987-04-19,3000,,207839,KING,PRESIDENT,,1981-11-17,5000,,107844,TURNER,SALESMAN,7698,1981-09-08,1500,0,307876,ADAMS,CLERK,7788,1987-05-23,1100,,207900,JAMES,CLERK,7698,1981-12-03,950,,307902,FORD,ANALYST,7566,1981-12-03,3000,,207934,MILLER,CLERK,7782,1982-01-23,1300,,10
dept表数据:
10,ACCOUNTING,NEW YORK20,RESEARCH,DALLAS30,SALES,CHICAGO40,OPERATIONS,BOSTON
载入数据:
load data local inpath '/home/tengyer/data/dept.txt' into table dept;load data local inpath '/home/tengyer/data/emp.txt' into table emp;
基本查询语法:
大小写不敏感
-- 同SQL的普通查询select * from emp;select empno,ename from emp;-- 指定别名(同SQL),可以使用as,也可以不写select empno a, ename as b from emp;-- 计算select sal + 1 from emp;
算术运算符:
| 运算符 | 描述 |
|---|---|
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 |
按位反 |
常用函数
类似SQL:
典型的查询会返回多行数据,可以使用 limit 限制返回的行数:
-- 返回5行数据select * from emp limit 5;-- 从第3行开始,返回3行数据select * from emp limit 2,3;
where语句
类似SQL中的where:
select * from emp where sal >1000;
操作符:
| 操作符 | 支持的数据类型 | 描述 |
|---|---|---|
A=B |
基本数据类型 | A等于B则返回TRUE;否则返回FALSE |
A<=>B |
基本数据类型 | A和B同时为Null,则返回TRUE;否则返回FALSE |
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 |
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。 表达式类似SQL的表达式: xxx%、 %xxx、 %xxx%、 xxx_ |
A RLIKE B, A REGEXP B |
STRING类型 | B是基于java的正则表达式,如果A与其匹配,则返回TRUE,反之返回FALSE。 匹配使用的是 jdk 中的正则表达式接口实现的,因为正则也依据其中的规则。 |
Group By分组
类似SQL中的 group by、having语句:
select deptno,avg(sal)from empgroup by deptnohaving avg(sal) > 2000;
Join语句
支持通常的SQL的join语句:
-- 内连接:join / inner joinselect e.ename,d.dnamefrom emp ejoin dept d on e.deptno=d.deptno;-- from多个表进行内连接select d.deptno, d.dname, e.enamefrom emp e,dept dwhere e.deptno=d.deptno-- 左外连接:left join / left outer joinselect d.deptno, d.dname, e.enamefrom dept dleft join emp e on e.deptno=d.deptno;-- 右外连接:right join / right outer joinselect e.ename,d.dname ,d.deptnofrom emp eright join dept d on e.deptno=d.deptno;-- 满连接:full join / full outer joinselect e.ename,d.dname ,d.deptnofrom emp efull join dept d on e.deptno=d.deptno;
Hive 也支持多表连接:Hive对每对JOIN连接的对象启动一个MapReduce任务,先启动一个MapReduce Job 对表1和表2进行连接,然后再启动一个MapReduce Job 将第一个MapReduce job 的输出和表3进行连接。
特别的:当多个表进行join连接时,如果每个 on 子句都使用相同的连接键,那么只会产生一个 MapReduce job。
Order By排序
类似SQL的 order by语句。
Order by是全局排序,只有一个Reducer。即使在MR中设置了多个Reducer,最后也只有一个Reducer。
hive设置Reducer个数:
set mapreduce.job.reduces=需要设置的个数;
排序规则:
- ASC:升序(默认)
- DESC:降序
select *from emp order by sal;
因为Order By只有一个Reducer,所以数据量比较大时,MR任务会失败,所以一般不会直接写order by语句。
Sort By 排序
对于大规模的数据集,order by的效率非常低,在很多情况下,并不需要全局排序,此时可以使用 sort by。
sort by 为每个 Reducer 产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。
设置Reducer个数:
-- 设置3个Reducerset mapreduce.job.reduces=3;
根据部门编号降序查看员工信息:
select * from emp sort by deptno desc;
将查询结果导入文件(按部门编号降序排序):
insert overwrite local directory '/home/tengyer/data/sortresult'row format delimitedfields terminated by ','select *from emp sort by deptno desc;
因为设置了3个Reducer,所以最后会生成3个结果文件。
在这3个结果文件内部,deptno是按降序排序的。但是对于全局,这3个结果文件是无序的。
这3个结果文件内的数据的分配默认是随机的。
Distribute by 分区
有些情况下,我们需要控制某个特定行应该到哪个Reducer,通常是为了进行后续的聚集操作。distribute by子句可以做这件事。
distribute by类似 MR 中partition(自定义分区),进行分区,结合 sort by使用。
distribute by语句位置在sort by语句之前。
示例:
先按照部门编号进行分区,然后按照员工编号进行降序排序。即:只关心部门内的员工号有序,无需使用order by进行全局排序
-- 设置3个Reducer。distribute by 必须设置多个Reducer才能看到效果set mapreduce.job.reduces=3;-- 使用deptno进行分区,分区内使用sort by对empno进行降序排序insert overwrite local directory '/home/tengyer/data/distributeresult'row format delimited fields terminated by ','select * from empdistribute by deptnosort by empno desc;
distribute by的分区规则是根据分区字段的hash码和reduce的个数进行取模,余数相同的分到同一个分区。所以如果两个
deptno的hash对reducer个数取的余数是相同的,那么这两个deptno会跑到同一个文件中。
Cluster by
当 distribute by 和 sort by字段相同时,可以使用 cluster by方式。
cluster by除了具有 distribute by的功能外,还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
以下两条SQL等价:
-- 使用cluster byselect * from empcluster by deptno;-- 使用distribute by + sort byselect * from empdistribute by deptnosort by deptno;
