挑战SQL语句面试题
目录
写在文章前
首先声明本人不是技术大佬、也不是培训老师,只是在工作中写过两年PL/SQL语句,有一定的数据处理经验,也是一个学习者。
在书上看到一份某企业招聘数据库工程师笔试题,其中有一个大题是SQL应用,就尝试做了一下。并且到DBMS中去验证了一番。这里将题目与作者写的答案分享出来,供学习数据库的朋友们参考、指正!
题目及解答
使用SCOTT/TIGER用户下的EMP和DEPT表完成下列练习,表结构说明如下:
EMP员工表(EMPNO员工编号、ENAME员工姓名、JOB工作、MGR上级编号、HIREDATE受雇日期、SAL薪金、COMM佣金、DEPTNO部门编号)
DEPT部门表(DEPRNO部门编号、DNAME部门名称、LOC地点)
工资=薪金 + 佣金
注: SCOTT/TIGER是Oracle数据库管理系统自带的数据库,所以下面的语句都是基于Oracle的。
1、列出所有至少有一个员工的部门。
答:第一种写法:select dname from dept where deptno in (select deptno from emp);
第二种写法:select distinct dp.dname from emp e left join dept dp on e.deptno=dp.deptno where dp.deptno is not null;
SQL> select dname from dept where deptno in (select deptno from emp);
DNAME
--------------
ACCOUNTING
RESEARCH
SALES
SQL> select distinct dp.dname from emp e left join dept dp on e.deptno=dp.deptno where dp.deptno is not null;
DNAME
--------------
ACCOUNTING
RESEARCH
SALES
2、列出薪金比SMITH多的所有员工
答:select ename from emp where sal >(select max(sal) from emp where ename='SMITH');
SQL> select ename from emp where sal >(select max(sal) from emp where ename='SMITH');
ENAME
----------
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
13 rows selected
3、列出所有员工及其上级的姓名
答:select e.ename,mg.ename as mgr from emp e left join emp mg on e.mgr = mg.empno;
SQL> select e.ename,mg.ename as mgr from emp e left join emp mg on e.mgr = mg.empno;
ENAME MGR
---------- ----------
FORD JONES
SCOTT JONES
JAMES BLAKE
TURNER BLAKE
MARTIN BLAKE
WARD BLAKE
ALLEN BLAKE
MILLER CLARK
ADAMS SCOTT
CLARK KING
BLAKE KING
JONES KING
SMITH FORD
KING
14 rows selected
4、列出受雇日期早于其直属上级的员工的所有员工。
答:select e.ename from emp e left join emp mg on e.mgr = mg.ename where e.hiredate< mg.hiredate;
SQL> select e.ename from emp e left join emp mg on e.mgr = mg.empno where e.hiredate< mg.hiredate;
ENAME
----------
ALLEN
WARD
BLAKE
JONES
CLARK
SMITH
6 rows selected
5、列出部门名称和这些部门的员工信息,同时列出没有员工的部门。
答:select dp.dname,e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm from dept dp left join emp e on dp.deptno=e.deptno;
SQL> select dp.dname,e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm from dept dp left join emp e on dp.deptno=e.deptno;
DNAME EMPNO ENAME JOB MGR HIREDATE SAL COMM
-------------- ----- ---------- --------- ----- ----------- --------- ---------
ACCOUNTING 7782 CLARK MANAGER 7839 1981-6-9 2450.00
ACCOUNTING 7839 KING PRESIDENT 1981-11-17 5000.00
ACCOUNTING 7934 MILLER CLERK 7782 1982-1-23 1300.00
RESEARCH 7566 JONES MANAGER 7839 1981-4-2 2975.00
RESEARCH 7902 FORD ANALYST 7566 1981-12-3 3000.00
RESEARCH 7876 ADAMS CLERK 7788 1987-5-23 1100.00
RESEARCH 7369 SMITH CLERK 7902 1980-12-17 800.00
RESEARCH 7788 SCOTT ANALYST 7566 1987-4-19 3000.00
SALES 7521 WARD SALESMAN 7698 1981-2-22 1250.00 500.00
SALES 7844 TURNER SALESMAN 7698 1981-9-8 1500.00 0.00
SALES 7499 ALLEN SALESMAN 7698 1981-2-20 1600.00 300.00
SALES 7900 JAMES CLERK 7698 1981-12-3 950.00
SALES 7698 BLAKE MANAGER 7839 1981-5-1 2850.00
SALES 7654 MARTIN SALESMAN 7698 1981-9-28 1250.00 1400.00
OPERATIONS
15 rows selected
6、列出所有工作为CLERK办事员的姓名及其部门名称。
答:select dp.dname,e.ename from dept dp right join emp e on dp.deptno=e.deptno where e.job='CLERK';
SQL> select e.ename,dp.dname from dept dp right join emp e on dp.deptno=e.deptno where e.job='CLERK';
ENAME DNAME
---------- --------------
SMITH RESEARCH
ADAMS RESEARCH
JAMES SALES
MILLER ACCOUNTING
7、列出薪金大于1500的各种工作。
答:select distinct job from emp where sal>1500;
SQL> select distinct job from emp where sal>1500;
JOB
---------
SALESMAN
PRESIDENT
MANAGER
ANALYST
8、列出在部门SALES销售部工作的员工姓名,假定不知道销售部的部门编号
答:第一种写法:select * from emp where deptno in (select deptno from dept where dname='SALES');
第二种写法:select e.ename from emp e left join dept dp on e.deptno=dp.deptno where dp.dname='SALES';
SQL> select e.ename from join emp e left dept dp on e.deptno=dp.deptno where dp.dname='SALES'
2 /
ENAME
----------
WARD
TURNER
ALLEN
JAMES
BLAKE
MARTIN
6 rows selected
SQL> select e.ename from emp e left join dept dp on e.deptno=dp.deptno where dp.dname='SALES';
ENAME
----------
WARD
TURNER
ALLEN
JAMES
BLAKE
MARTIN
6 rows selected
9、列出薪金高于公司平均薪金的员工。
答:select ename from emp where sal > (select avg(sal) from emp);
SQL> select ename from emp where sal > (select avg(sal) from emp);
ENAME
----------
JONES
BLAKE
CLARK
SCOTT
KING
FORD
6 rows selected
10、列出于员工SCOTT从事相同工作的员工。
答:select e.ename from emp e where e.job in (select job from emp where ename='SCOTT');
SQL> select e.ename from emp e where e.job in (select job from emp where ename='SCOTT');
ENAME
----------
FORD
SCOTT
11、列出薪金等于部门编号为30的员工的所有员工的姓名和薪金。
答:第一种: select ename,sal from emp where sal in(select sal from emp where deptno=30);
第二种:select distinct e.ename,e.sal from emp e left join emp e30 on e30.deptno=30 where e.sal=e30.sal and e30.empno is not null;
SQL> select ename,sal from emp where sal in(select sal from emp where deptno=30);
ENAME SAL
---------- ---------
ALLEN 1600.00
MARTIN 1250.00
WARD 1250.00
BLAKE 2850.00
TURNER 1500.00
JAMES 950.00
6 rows selected
SQL> select distinct e.ename,e.sal from emp e left join emp e30 on e30.deptno=30 where e.sal=e30.sal and e30.empno is not null;
ENAME SAL
---------- ---------
ALLEN 1600.00
MARTIN 1250.00
TURNER 1500.00
JAMES 950.00
WARD 1250.00
BLAKE 2850.00
6 rows selected
12、列出薪金大于在部门编号为30的所有员工的所有员工的姓名和薪金。
答:select ename,sal from emp where sal > (select max(sal) from emp where deptno=30);
SQL> select ename,sal from emp where sal > (select max(sal) from emp where deptno=30);
ENAME SAL
---------- ---------
JONES 2975.00
SCOTT 3000.00
KING 5000.00
FORD 3000.00
13、列出在每个部门工作的员工数量、平均工资和平均服务期限。
答:select count(empno) as 员工数量,round(avg(sal+nvl(comm,0))) as 平均工资,round(avg(months_between(sysdate,hiredate))/12) as 平均期限 from emp group by deptno;
SQL> select count(empno) as 员工数量,round(avg(sal+nvl(comm,0))) as 平均工资,round(avg(months_between(sysdate,hiredate))/12) as 平均期限 from emp group by deptno;
员工数量 平均工资 平均期限
---------- ---------- ----------
6 1933 40
5 2175 38
3 2917 40
14、列出所有员工的姓名、部门名称、工资
答:select e.ename,e.sal,dp.dname from emp e left join dept dp on e.deptno = dp.deptno;
SQL> select e.ename,e.sal,dp.dname from emp e left join dept dp on e.deptno = dp.deptno;
ENAME SAL DNAME
---------- --------- --------------
MILLER 1300.00 ACCOUNTING
KING 5000.00 ACCOUNTING
CLARK 2450.00 ACCOUNTING
FORD 3000.00 RESEARCH
ADAMS 1100.00 RESEARCH
SCOTT 3000.00 RESEARCH
JONES 2975.00 RESEARCH
SMITH 800.00 RESEARCH
JAMES 950.00 SALES
TURNER 1500.00 SALES
BLAKE 2850.00 SALES
MARTIN 1250.00 SALES
WARD 1250.00 SALES
ALLEN 1600.00 SALES
14 rows selected
15、列出所有部门的详细信息和人数
答:select dp.deptno,dp.dname,dp.loc,nvl(c.count,0) from dept dp left join (select deptno,count(*) as count from emp group by deptno) c on dp.deptno=c.deptno;
SQL> select dp.deptno,dp.dname,dp.loc,nvl(c.count,0) from dept dp left join (select deptno,count(*) as count from emp group by deptno) c on dp.deptno=c.deptno;
DEPTNO DNAME LOC NVL(C.COUNT,0)
------ -------------- ------------- --------------
10 ACCOUNTING NEW YORK 3
20 RESEARCH DALLAS 5
30 SALES CHICAGO 6
40 OPERATIONS BOSTON 0
16、列出各种工作的最低工资
答:select job,min(sal+nvl(comm,0)) as pjgz from emp group by job;
SQL> select job,min(sal+nvl(comm,0)) as pjgz from emp group by job;
JOB PJGZ
--------- ----------
CLERK 800
SALESMAN 1500
PRESIDENT 5000
MANAGER 2450
ANALYST 3000
17、列出工作为MANAGER的员工的最低薪金
答:select job,min(sal) as zdgz from emp group by job having job ='MANAGER';
SQL> select job,min(sal) as zdgz from emp group by job having job ='MANAGER'
2 /
JOB ZDGZ
--------- ----------
MANAGER 2450
18、列出所有员工年工资,按年薪从低到高排序。
答:select ename,sal+nvl(comm,0) as ngz from emp order by sal asc;
SQL> select ename,sal+nvl(comm,0) as ngz from emp order by sal asc;
ENAME NGZ
---------- ----------
SMITH 800
JAMES 950
ADAMS 1100
WARD 1750
MARTIN 2650
MILLER 1300
TURNER 1500
ALLEN 1900
CLARK 2450
BLAKE 2850
JONES 2975
SCOTT 3000
FORD 3000
KING 5000
14 rows selected
个人对题目的思考
从考试题目的问题可以看出,解答考试题的核心还是答案要“踩点”,即写到考核的点上,这一点与生产环境实际使用还是有很大区别。
题目设置的表结构不复杂,且使用了Oracle自带数据库作为基础数据,所问题目全部是查询语句,在查询语句中,应该是想考察应试者对数据的查询分析的能力。
在答题中,使用了查询语句基本格式,联表查,子查询的基本格式,聚合函数,单行函数,时间、数字计算等知识技能。考得很基础、一般的教程都有。但却不容易做好。因为在笔试环境中,使用手写SQL、且无法测试验证,这对基本功的要求还是很高的。平时还是要在命令行中多练习,多实践。
此外,除非特别提到“特殊情况”,如:数据量大需考虑优化、有重复数据等,解答考试题目时还是默认在最简单的情况下答题,因为手写语句不宜过长,影响阅读。