Hive中执行SQL语句时,出现类似于“Display all 469 possibilities? (y or n)”的错误,
根本原因是因为SQL语句中存在tab键导致,tab键在linux系统中是有特殊含义的。
1. 基本查询
desc formatted stu_buck;
desc stu_buck;
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Select
查询语句语法: 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]
创建部门表
create table if not exists dept(
deptno int,
dname string,
loc int)
row format delimited fields terminated by '\t';
创建员工表
hive (default)> create table if not exists emp(
> empno int, enane string, job string, mgr int, hiredate string, sal double, comm double, deptno int)
> row format delimited fields terminated by '\t';
导入数据
hive (default)> load data local inpath '/opt/module/datas/emp.txt' into table emp;
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table dept;
hive (default)> select * from emp;
hive (default)> select empno, ename from emp;
hive (default)> select ename AS name, deptno dn from emp; //列别名
hive (default)> select sal +1 from emp; //算术运算
常用函数
count(*)
max(sal)
min(sal)
sum(sal)
avg(sal)
LIMIT子句用于限制返回的行数。
hive (default)> select * from emp limit 5;
注意:
(1)SQL 语言大小写不敏感。
(2)SQL 可以写在一行或者多行
(3)关键字不能被缩写也不能分行
(4)各子句一般要分行写。
(5)使用缩进提高语句的可读性。
算术运算符
|
运算符 |
描述 |
|
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按位取反 |
① Where语句
使用WHERE子句,将不满足条件的行过滤掉, 注意:where子句中不能使用字段别名。
hive (default)> select * from emp where sal >1000;
比较运算符(Between/In/ Is Null)
select * from emp where sal between 500 and 1000; //工资在500到1000的员工信息
select * from emp where sal IN (1500, 5000); //查询工资是1500或5000的员工信息
select * from emp where comm is null; //comm为空的所有员工信息
② Like和RLike
1)使用LIKE运算选择类似的值
2)选择条件可以包含字符或数字:
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
3)RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
select * from emp where sal LIKE '2%'; //查找以2开头薪水的员工信息
select * from emp where sal LIKE '_2%'; //查找第二个数值为2的薪水的员工信息
select * from emp where sal RLIKE '[2]'; //查找薪水中含有2的员工信息
③ 逻辑运算符(And/Or/Not)
操作符 含义
AND 逻辑并
OR 逻辑或
NOT 逻辑否
select * from emp where sal>1000 and deptno=30; //查询薪水大于1000,部门是30
select * from emp where sal>1000 or deptno=30; //查询薪水大于1000,或者部门是30
select * from emp where deptno not IN(30, 20); //查询除了20部门和30部门以外的员工信息
not in
not null尽量不使用它们,影响效率
2. 分组
GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
- 1)where后面不能写分组函数,而having后面可以使用分组函数。
- 2)having只用于group by分组统计语句。
分组group by xx字段,select后边跟的字段必须跟group by字段有关聚合函数如count( * )或者这个字段;不能是别的字段!!!
select t1.base, t1.name, count(*) from (select concat(constellation, ",", blood_type) base, name from person_info) t1 group by base; select后边不能要name;
group
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; //计算emp每个部门中每个岗位的最高薪水
group by了,select后边的字段必须是group by的字段或者使用聚合函数,否则不能加其他字段;
having
having与where不同点
(1)where后面不能写分组函数,而having后面可以使用分组函数。
(2)having只用于group by分组统计语句。
select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000; //求每个部门的平均薪水大于2000的部门
select substring(orderdate, 6, 2),count(*) from business where xxx group by substring(orderdate,6,2);
执行顺序: from...where...select...group by...having...order by...
select substring(orderdate, 6, 2) month, count(*) from business group by month;
Error: Error while compiling statement: FAILED: SemanticException Line 0:-1 Invalid table alias or column reference 'year':
(possible column names are: name, orderdate, cost) (state=42000,code=40000)
order by date desc, market_id asc; ---先按照date降序,再按 market_id升序排列;
date market_id total_fee
2019-10-18 110 23000
2019-10-18 110 13000
2019-10-18 141 1400
2019-10-18 141 2250
2019-10-18 218 4000
2019-10-15 170 1100
2019-10-15 183 2300
2019-10-15 218 4500
2019-10-08 110 0
2019-10-08 234 0
查询仅出现一次的数据
SELECT name,count(name) AS count_times FROM tb_test GROUP BY name HAVING count_times = 1;
查询语句返回某字段出现超过1次的所有记录
select * from stu where sname in (select sname from stu group by sname having count(sname)>1);
有重复的sname的记录,并计算相同sname的数量
select *,count(sname)as count from stu group by sname having (count(sname)>1);
Hive取非Group by字段数据的方法,但可加聚合函数如count、sum、avg、max等
3. Join语句
Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。
表的别名好处: 1)使用别名可以简化查询。 2)使用表名前缀可以提高执行效率。
① 内连接
内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。
select e.empno, e.emane, d.deptno, d.dname from emp e join dept d on e.deptno=d.deptno;
② 左外连接
JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
select e.empno, e.emane, d.deptno, d.dname from emp e left join dept d on e.deptno=d.deptno;
③ 右外连接
JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。
select e.empno, e.ename, d.deptno from emp e right join dept d on e.deptno = d.deptno;
④ 满外连接
将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
select e.empno, e.ename, d.deptno from emp e full join dept d on e.deptno = d.deptno;
⑤ 多表连接
注意:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
hive (default)> create table if not exists location(
> loc int, loc_name string)
> row format delimited fields terminated by '\t';
hive (default)> load data local inpath '/opt/module/datas/location.txt' into table location;
多表连接查询
select
e.empno, e.emane, d.dname, l.loc_name
from emp e join dept d on e.deptno=d.deptno
join location l on d.loc=l.loc;
//number of mappers: 1; number of reducers: 0
大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。
首先启动一个MapReduce job对表e和表d进行连接操作,
然后会再启动一个MapReduce job将第一个MapReduce job的输出和表l进行连接操作。
注意:为什么不是表d和表l先进行连接操作呢?这是因为Hive总是按照从左到右的顺序执行的。
优化:当对3个或者更多表进行join连接时,如果每个on子句都使用相同的连接键的话,那么只会产生一个MapReduce job。
⑥ 笛卡尔积
笛卡尔集会在下面条件下产生
(1)省略连接条件
(2)连接条件无效
(3)所有表中的所有行互相连接
select empno, dname from emp, dept;
⑦ 连接谓词中不支持or
4. 排序| 全局order by、reduce内部sort by、分区distribute by
① 全局排序order by, 只有一个Reduce,全局查找; 默认升序, desc是降序; select * from emp order by sal; //默认升序 select * from emp order by sal desc; //降序 ② 按别名排序 | 多个列排序 select ename,deptno, sal*2 twosalary from emp order by twosalary; //order by 字段;select 字段,必须写上排序的字段,否则出错!! select deptno, emane, sal from emp order by deptno, sal; //按照部门和工资升序排序 deptno相同了再按sal排序; mappers: 1; number of reducers: 1 ③ 每个MapReduce内部排序 sort by 对于大规模的数据集order by的效率非常低;在很多情况下,并不需要全局排序,此时可以使用sort by。 Sort by为每个reducer产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。 设置reduce个数 set mapreduce.job.reduces=3; set mapreduce.job.reduces; select * from emp sort by deptno desc; //根据部门编号降序查看员工信息 insert overwrite local directory '/opt/module/datas/sortby-result' select * from emp sort by deptno desc; //将查询结果导入到文件中(按照部门编号降序排序) // number of mappers: 1; number of reducers: 3 ④ 分区排序 distribute by Distribute By:在有些情况下,我们需要控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。 distribute by 子句可以做这件事。distribute by类似MR中partition(自定义分区),进行分区,结合 sort by使用。 对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。 distribute by的分区规则是: 根据分区字段的hash码与reduce的个数进行模除后,余数相同的分到一个区。 Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前 insert overwrite local directory '/opt/module/datas/sortby-result' select * from emp sort by deptno desc; insert overwrite local directory '/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc; ⑤ cluster by 当distribute by和sorts by字段相同时,可以使用cluster by方式。 cluster by除了具有distribute by的功能(分区)外还兼具sort by的功能。即reduce内部排序的功能。 但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。 select * from emp cluster by deptno; select * from emp distribute by deptno sort by deptno; 注意:按照部门编号分区,不一定就是固定死的数值,可以是20号和30号部门分到一个分区里面去。
5. 抽样查询
对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。
语法: TABLESAMPLE(BUCKET x OUT OF y)
注意:x的值必须小于等于y的值,否则
FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause for table stu_buck。
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)个和第
3(x+y)个bucket的数据。
tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) 。
Bucket即HDFS上的目录数、桶的个数;
总的bucket数量数 == hdfs中的目录数;
select * from stu_buck tablesample(bucket 2 out of 2 on id);
+--------------+----------------+--+
| stu_buck.id | stu_buck.name |
+--------------+----------------+--+
| 1009 | ss9 |
| 1005 | ss5 |
| 1001 | ss1 |
| 1013 | ss13 |
| 1003 | ss3 |
| 1011 | ss11 |
| 1007 | ss7 |
| 1015 | ss15 |
tablesample(bucket 2 out of 2 on id) //总共抽取(4/2=2)个bucket的数据, 抽取第2个、第2+2即4个 bucket的开始;总共抽取2个bucket的数据。
select * from stu_buck tablesample(bucket 3 out of 8 on id); //总共抽取(4/8=0.5)个bucket的数据,抽取第3个bucket的0.5个数据;
+--------------+----------------+--+
| stu_buck.id | stu_buck.name |
+--------------+----------------+--+
| 1010 | ss10 |
| 1002 | ss2 |
+--------------+----------------+--+
2 rows selected (0.148 seconds)
函数
1. 系统内置函数
1)查看系统自带的函数
hive> show functions;
2)显示自带的函数的用法
hive> desc function upper;
3)详细显示自带的函数的用法
hive> desc function extended regexp_replace;
2. 常用内置函数
空字段赋值
NVL:给值为NULL的数据赋值,它的格式是NVL( value,default_value)。它的功能是如果value为NULL,则NVL函数返回default_value的值,否则返回value的值,如果两个参数都为NULL ,则返回NULL。
select comm, nvl(comm, -1) from emp;
+---------+---------+--+
| comm | _c1 |
+---------+---------+--+
| NULL | -1.0 |
| 300.0 | 300.0 |
| 500.0 | 500.0 |
| NULL | -1.0 |
| 1400.0 | 1400.0 |
| NULL | -1.0 |
| NULL | -1.0 |
| NULL | -1.0 |
| NULL | -1.0 |
| 0.0 | 0.0 |
| NULL | -1.0 |
| NULL | -1.0 |
| NULL | -1.0 |
| NULL | -1.0 |
+---------+---------+--+
14 rows selected (0.125 seconds)
select comm, nvl(comm, mgr) from emp; //如果员工的comm为NULL,则用领导id代替
CASE WHEN
建表load数据
hive (default)> create table emp_sex( > name string, dept_id string, sex string) > row format delimited fields terminated by '\t'; OK Time taken: 1.169 seconds hive (default)> load data local inpath '/opt/module/datas/emp_sex.txt' into table emp_sex; Loading data to table default.emp_sex Table default.emp_sex stats: [numFiles=1, totalSize=78] OK Time taken: 0.516 seconds