网上很多数据库例题都有的两张表:emp和dept 表
员工信息表emp:
字段:员工id,员工名字,工作岗位,部门经理,受雇日期,薪水,奖金,部门编号
部门信息表dept:
字段:部门编号,部门名称,部门地点
英文名:DEPTNO,DEPTNAME,DEPTADDR
建表语句:
create table emp( EMPNO int ,ENAME string ,JOB string ,MGR int ,HIREDATE string ,SAL int ,BonUS int ,DEPTNO int ) row format delimited fields terminated by ',';
create table dept( DEPTNO int ,DEPTNAME string ,DEPTADDR string ) row format delimited fields terminated by ',';
导入数据后查询
hive> select * from emp
为了方便观看,我给上面加了每列的字段名称
hive> select * from dept;
题目1. 列出至少有一个员工的所有部门
//使用having hive> select distinct(dept.deptname) from (select deptno from emp group by deptno having count(*)>=1) as a join dept on a.deptno=dept.deptno;
这里为什么要写第二种方法,因为hive的语法和mysql有的地方不太相同
所以部分mysql写的没有问题的语句,hive中需要转换方法写, 通常就是多表连接和多写点二次查询,比较麻烦
//方式2:二次查询 select distinct(dept.deptname) from (select deptno from (select deptno,count(*) as num from emp group by deptno) as a where num>=1) as b join dept on b.deptno=dept.deptno;
2.列出薪金比“SMITH”多的所有员工
mysql写法:
select ename from emp where sal>(select sal from emp where name='SMITH');
但是hive不支持where后面跟子查询 :in可以跟子查询,但是<,>,=不支持
select e.ENAME ,e.SAL from (select ENAME ,SAL ,1 as cid from emp)e left join (select SAL ,1 as cid from emp where ENAME='SMITH') s on e.cid=s.cid where e.SAL>s.SAL;
下面来解析一下,首先根据题目中说找出比SMITH工资高的人,
那么我就先查询出SMITH工资是多少,
然后 把所有人的工资和这个值比较,hive不支持不等值连接,where后面子查询。
所有我们考虑给这2个查询表每行都打上一个标记作为一个新的字段,这样就可以根据这个新的字段进行表连接,然后我在这个查询基础上通过where筛选出工资比SMITH工资多的
3. 列出所有员工的姓名及其直接上级的姓名。
和mysql一样的写法,利用表的自连接,将第一张表的领导标号与第二张表的员工标号相同作为连接条件
select a.ename,b.ename from emp a join emp b on a.mgr=b.empno
4. 列出受雇日期早于其直接上级的所有员工
还是利用表的自连接,再通过where筛选出hiredate比领导早的
select a.ename from emp a join emp b on a.mgr=b.empno where a.hiredate5. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
做法与mysql相同,利用左连接,显示左边的全部信息,右边为空的会使用null填充
select b.DEPTNAME,a.* from dept b left join emp a on a.deptno=b.deptno;上面的部门表中出现2个相同的部门名称,但是地理位置不同,这里会出现重复的人名
6.列出所有“CLERK”(办事员)的姓名及其部门名称。
//注意distinct去重,要放在最前面,不能有字段在distinct前面 select distinct b.deptname,a.ename from emp a join dept b on a.deptno=b.deptno where a.job='CLERK';7. 列出最低薪金大于1500的各种工作。
//使用having select job from emp group by job having min(sal)>1500 ;//使用where select job from (select job,min(sal) as minsal from emp group by job) as tmp where minsal>1500;8.列出在部门“SALES”(销售部)工作的员工的姓名,假定不知道销售部的部门编号
题目我有点看不懂,假定不知道销售部门的编号,我看了解析说: sal的部门编号不能直接用,需要自己查询出对应的部门编号
//通常都是这么写,但是题目要求我们不知道部门编号 select a. ename from emp a join dept b on a.deptno=b.deptno where b.Deptname='SALES';//所以下面的语句需要改动,我们过滤出部门编号 select deptno from dept where deptname='SALES' //再从筛选出的部门编号里匹配出对应的人员名字, //我使用的是hive1.2.1版本,可以使用where后面跟上in子查询语句 //但是>,<,=还是不支持的 select ename from emp where deptno in ( select deptno from dept where deptname='SALES' );9. 列出薪金高于公司平均薪金的所有员工
//mysql中的写法 select * from emp where sal>(select avg(sal) from emp) as a;//hive中不支持where子查询,所以还是老样子手动打上一个标签,然后连接,再通过where做筛选 select a.* from (select *,1 as cli from emp) a join (select avg(sal) as sal,1 as cli from emp) b on a.cli=b.cli where a.sal>b.sal;10.列出与“SCOTT”从事相同工作的所有员工。
//mysql中的答案 select ename from emp where job in (select job from emp where ename='SMITH');在hive中运行上面的按理说应该是通过的,但是报错了
FAILED: SemanticException [Error 10249]: Line 1:70 Unsupported SubQuery expression 'ENAME': SubQuery cannot use the table alias: emp; this is also an alias in the Outer Query and SubQuery contains a unqualified column reference翻译内容:
第3:27行不支持的子查询表达式“ename”:
子查询不能使用表别名:emp;这也是外部查询中的别名,子查询包含非限定列引用
//所以子查询和外面的查询字段不能重复,必须起别名 select ename from emp where job in (select job from emp e where e.ename='SMITH') and ename<>'SMITH';11.列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。
select ename,sal from emp where deptno=30;12.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。
//mysql写法,显然在hive不能用,有子查询,并且是>,<,=的类型 select ename,sal from emp where sal>(select sal from emp e where e.deptno=30)//hive写法 select a.ename,a.sal from (select *,1 as cli from emp) a join (select max(sal) as max,1 as cli from emp where deptno=30) b on a.cli=b.cli where a.deptno<>30 and a.sal>b.max;13.列出在每个部门工作的员工数量、平均工资和平均服务期限。
hive支持的获取当前时间 :
CURRENT_TIMESTAMP(); 精确到 年,月,日,时,分,秒,毫秒
CURRENT_DATE(); 精确到 年,月,日求为企业的服务期限,那么就是时间相减datediff(current_date(),hiredate)
select count(*) ,avg(sal) ,avg(datediff(current_date(),hiredate)) from emp group by deptno;结果看起来有点长,保留2位小数
select count(*) ,round(avg(sal),2) ,round(avg(datediff(current_date(),hiredate)),2) from emp group by deptno;14.列出所有员工的姓名、部门名称和工资。
select ename ,deptname ,sal from emp a join dept b on a.deptno=b.deptno;
15.列出所有部门的详细信息和部门人数。
select a.deptno ,a.deptname ,a.deptaddr ,b.num from dept a left join (select count(*) as num,deptno from emp group by deptno) b on a.deptno=b.deptno;下面分析一下为什么这么做
select t.deptname.t.deptno,count(*) from (select deptname ,b.deptno ,b.DEPTADDR from dept b left join emp a on a.deptno=b.deptno) t group by deptno,deptaddr;
16.列出各种工作的最低工资select job,min(sal) from emp group by job;17.列出各个部门的MANAGER(经理)的最低薪金
where后面跟in子查询,mysql和hive都可以使用
select deptno, min(sal) from emp where empno in (select mgr from emp) group by deptno;
18.列出所有员工的年工资,按年薪从低到高排序//此处nvl函数是帮助转化为null的值,如果是空,就转换为后面设置的大小 select ename ,(sal*12+nvl(bonus,0)) as money from emp order by money;19. 列出每个部门薪水前两名最高的人员名称以及薪水。
//准备工作:先开一个窗口,将部门的排名给打上去 select ename ,sal ,row_number() over(partition by deptno order by sal) rn ,deptno from emp;然后我们通过where筛选出排名小于等于2的:
select t.ename ,t.deptno ,t.sal from ( select ename ,sal ,row_number() over(partition by deptno order by sal) rn ,deptno from emp ) t where t.rn<=2;
20. 列出每个员工从受雇开始到2018-12-12 为止共受雇了多少天select ename ,datediff('2018-12-12',hiredate)as days from emp ;欢迎分享,转载请注明来源:内存溢出
评论列表(0条)