这里涉及聚合函数,分析函数,条件函数,以及自身映射。
一共有以下几张表(EMP,Dept)以及表的结构和下面的36条基础题。
下面我会用*号特定展示,那些比较重要,优先处理。
1.1 列出至少有两个员工的所有部门。
SELECT DEPTNO,COUNT(1)
FROM EMP
GROUP BY DEPTNO
HAVING COUNT(1) >= 2;
1.2 查询工资大于或者等于2000 的员工信息
SELECT * FROM EMP WHERE SAL >= 2000;
1.3 查询至少有两个员工的工资不低于2000的部门编号
SELECT DEPTNO,COUNT(1)
FROM EMP
WHERE SAL >= 2000
GROUP BY DEPTNO
HAVING COUNT(1) >= 2;
2.1列出薪金比“SMITH”多的所有员工。
SELECT * FROM EMP WHERE SAL >(SELECT SAL FROM EMP WHERE ENAME = 'SMITH');
2.2 查询工资 与 SCOTT 相同的员工信息
SELECT * FROM EMP WHERE SAL = (SELECT ENAME FROM EMP WHERE ENAME = 'SCOTT');
2.3 查询工资 与 SCOTT 相同的员工信息,并且不返回SCOTT自己的信息
SELECT * FROM EMP WHERE SAL = (SELECT ENAME FROM EMP WHERE ENAME = 'SCOTT') AND ENAME <> 'SCOTT';
3.*列出所有员工的姓名及其直接上级的姓名。
SELECT A.ENAME,B.ENAME
FROM EMP A
LEFT JOIN EMP B
ON A.MGR = B.EMPNO;
PS : 自表映射(关联)
关键在于由谁作为连接字段去映射自表,谁在前谁在后。
因为EMPNO和MGR都属于员工编号,而且多个员工对应一个MGR(经理)
4.列出受雇日期早于其直接上级的所有员工。
SELECT A.*
FROM EMP A,EMP B
WHERE A.MGR = B.EMPNO
AND A.HIREDATE < B.HIREDATE;
PS: 这是第三题的拓展,增加了一条筛选条件。
日期比较早的,则表示受雇日期越大的,就离现在越近。
5.*列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
SELECT A.DNAME,E.*
FROM DEPT A LEFT JOIN EMP E
ON A.DEPTNO = E.DEPTNO;
PS: 谁为主表的问题,看清宾语。
要的是部门名称和这个员工信息,同时要列出没有部门的员工。
第一种情况,假如以EMP为主表,则EMP表上所有的员工都会返回,只匹配到员工表上所有信息,而如果还有一些员工没在部门内的,则全不会返回。
第二种情况,假如以Dept为主表,则Dept表上所有的部门都会返回,只匹配到的员工则会有信息,没有的则不返回。
1)第一种情况:
第二种情况:
6.列出所有“CLERK”(办事员)的姓名及其部门名称。
SELECT E.ENAME,D.DNAME
FROM EMP E,DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND E.JOB = 'CLERK';
7.列出最低薪金大于1500的各种工作。
SELECT JOB,MIN(SAL)
FROM EMP
GROUP BY JOB
HAVING MIN(SAL) > 1500;
8.列出在部门“SALES”(销售部)工作的员工的姓名,假定不知道销售部的部门编号。
SELECT ENAME FROM EMP WHERE DEPTNO = (SELECT DEPTNO FROM DEPT WHERE DNAME = 'SALES');
9.列出薪金高于公司平均薪金的所有员工。
SELECT * FROM EMP WHERE SAL >(SELECT AVG(SAL) FROM EMP);
10.列出与“SCOTT”从事相同工作的所有员工。
SELECT * FROM EMP WHERE JOB = (SELECT JOB FROM EMP WHERE ENAME = 'SCOTT');
11.列出薪金等于部门30中员工的薪金的非30号部门的员工的姓名和薪金。
SELECT ENAME,SAL FROM EMP WHERE SAL IN (SELECT SAL FROM EMP WHERE DEPTNO=30) AND DEPTNO!=30;
12.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。
SELECT A.ENAME,A.SAL FROM EMP A WHERE A.SAL>(SELECT MAX(B.SAL) FROM EMP B WHERE B.DEPTNO=30);
13.列出在每个部门工作的员工数量、平均工资和平均服务期限。
SELECT DEPTNO,COUNT(1),AVG(SAL),AVG(SYSDATE - HIREDATE) FROM EMP GROUP BY DEPTNO;
PS:服务期限就用自带函数sysdate 与入职时间相减,最后再求平均。
14.列出所有员工的姓名、部门名称和工资。
SELECT E.ENAME, D.DNAME, E.SAL FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO;
PS : 所有的员工,所有的员工只存在EMP表里。因此,EMP表作为主表。
15.*列出所有部门的详细信息和部门人数。
SELECT D.DEPTNO, D.DNAME, D.LOC, CT.CT1
FROM DEPT D,
(SELECT DEPTNO, COUNT(DEPTNO) CT1 FROM EMP GROUP BY DEPTNO) CT
WHERE D.DEPTNO = CT.DEPTNO(+);
先看定语,所有部门的详细信息,这那张表最完整,只有在Dept表里有。
然后再Left Join 作为两张表的链接,在Where 后面会添加(+)则代表谁为主表。
按照传统的写法,则如下:
SELECT D.DEPTNO, D.DNAME, COUNT(E.DEPTNO)
FROM DEPT D, EMP E
WHERE D.DEPTNO = E.DEPTNO(+)
GROUP BY D.DEPTNO, D.DNAME;
16.列出各种工作的最低工资。
SELECT E1.JOB,MIN(E1.SAL) FROM EMP E1 GROUP BY E1.JOB
17.列出各个部门的MANAGER(经理)的最低薪金。
SELECT deptno, MIN(sal) FROM emp WHERE job='MANAGER' GROUP BY deptno;
18.列出所有员工的年工资,按年薪从低到高排序。
SELECT (SAL+NVL(COMM,0))*12 年薪 FROM EMP ORDER BY 年薪;
19.查出emp表中薪水在3000以上(包括3000)的所有员工的员工号、姓名、薪水。
SELECT EMPNO,ENAME,SAL FROM EMP WHERE SAL>=3000;
20.查询出所有薪水在’ALLEN’之上的所有人员信息。
SELECT * FROM EMP WHERE SAL>(SELECT SAL FROM EMP WHERE ENAME='ALLEN');
21.查询出emp表中部门编号为20,薪水在2000以上(不包括2000)的所有员工,显示他们的员工号,姓名以及薪水,以如下列名显示:员工编号 员工名字 薪水
SELECT EMPNO AS 员工编号, ENAME AS 员工名字,SAL AS 薪水 FROM EMP E WHERE DEPTNO=20 AND SAL>2000;
22.查询出emp表中所有的工作种类(无重复)
SELECT DISTINCT JOB FROM EMP;
SELECT JOB FROM EMP GROUP BY JOB;
23.查询出所有奖金(comm)字段不为空的人员的所有信息。
SELECT * FROM EMP WHERE COMM IS NOT NULL;
24.查询出薪水在800到2500之间(闭区间)所有员工的信息。(注:使用两种方式实现and以及between and)
SELECT * FROM EMP WHERE SAL>=800 AND SAL<=2500;
SELECT * FROM EMP WHERE SAL BETWEEN 800 AND 2500;
25.查询出员工号为7521,7900,7782的所有员工的信息。(注:使用两种方式实现,or以及in)
SELECT * FROM EMP WHERE EMPNO IN (7521,7900,7782);
SELECT * FROM EMP WHERE EMPNO=7521 OR EMPNO=7900 OR EMPNO=7782;
26.查询出名字中有“A”字符,并且薪水在1000以上(不包括1000)的所有员工信息。
PS:INSTR(C1,C2,I,J) 在一个字符串中搜索指定的字符,返回发现指定的字符的位置;
C1 被搜索的字符串
C2 希望搜索的字符串
I 搜索的开始位置,默认为1
J 出现的位置,默认为1
SQL> select instr("abcde",'b'); 结果是2,即在字符串“abcde”里面,字符串“b”出现在第2个位置。如果没有找到,则返回0;不可能返回负数
SELECT * FROM EMP WHERE ENAME LIKE '%A%' AND SAL > 1000;
SELECT * FROM EMP WHERE INSTR(ENAME,'A',1,1) <> 0 AND SAL > 1000;
27.查询出名字第三个字母是“M”的所有员工信息。
SELECT * FROM EMP WHERE ENAME LIKE '__M%';
SELECT * FROM EMP WHERE INSTR(ENAME,'M',3,1) = 3;
28.将所有员工按薪水升序排序,薪水相同的按照入职时间降序排序。
PS: 两个先后排序,用逗号隔开。
SELECT * FROM EMP A ORDER BY A.SAL ASC,A.HIREDATE DESC;
29.将所有员工按照名字首字母升序排序,首字母相同的按照薪水降序排序。
PS:Substr 函数
1、作用:用来截取数据库某个字段中的一部分。
2、语法:substr(string,start,length)
string参数:必选。数据库中需要截取的字段。
start参数:必选。
正数,从字符串指定位子开始截取;负数,从字符串结尾指定位子开始截取;0,在字符串中第一个位子开始截取。1,同理。(特殊)。length参数:可选。需要截取的长度。缺省,即截取到结束位置。
SELECT * FROM EMP ORDER BY SUBSTR(ENAME,1,1),SAL DESC;
30.查询出最早工作的那个人的名字、入职时间和薪水。
SELECT ENAME,HIREDATE,SAL FROM EMP WHERE HIREDATE = ( SELECT MIN(HIREDATE) FROM EMP);
31*.显示所有员工的名字、薪水、奖金,如果没有奖金,暂时显示100.
PS :一NVL函数是一个空值转换函数
NVL(表达式1,表达式2)如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值。 该函数的目的是把一个空值(null)转换成一个实际的值。其表达式的值可以是数字型、字符型和日期型。但是表达式1和表达式2的数据类型必须为同一个类型。
对数字型 NVL( comm,0);
对字符型 NVL( TO_CHAR(comm), 'No Commission')
对日期型 NVL(hiredate,' 31-DEC-99')
SELECT
E.ENAME,
E.SAL,
NVL(E.COMM,100)
FROM EMP E;
32.显示出薪水最高人的职位。
SELECT E.JOB FROM EMP E WHERE SAL=(SELECT MAX(SAL) FROM EMP);
33.查出emp表中所有部门的最高薪水和最低薪水,部门编号为10的部门不显示。
SELECT DEPTNO,MAX(SAL),MIN(SAL)
FROM EMP
WHERE DEPTNO <> 10
GROUP BY DEPTNO;
34.删除10号部门薪水最高的员工。
DELETE FROM EMP WHERE EMPNO IN (SELECT EMPNO FROM EMP WHERE SAL = (SELECT MAX(SAL) FROM EMP WHERE DEPTNO = 10) AND DEPTNO = 10) ;
DELETE FROM EMP WHERE SAL = (SELECT MAX(SAL) FROM EMP WHERE DEPTNO = 10) AND DEPTNO = 10;
DELETE FROM EMP WHERE DEPTNO = 10 AND SAL = (SELECT MAX(SAL) FROM EMP WHERE DEPTNO = 10);
35.将薪水最高的员工的薪水降30%。
注意:所有的更改后面记得加上Where,不然整张表都更新。
第二,任何的更新操作后面要加上Commit;
UPDATE EMP SET e.SAL=e.sal*0.7 WHERE SAL=(SELECT MAX(E.SAL) FROM EMP E);
36.查询员工姓名,工资和 工资级别(工资>=3000 为3级,工资>2000 为2级,工资<=2000 为1级)
注意: 每个条件判断条件后面不用写','号.
SELECT E.ENAME,E.SAL,CASE WHEN (E.SAL)>=3000 THEN '3级'
WHEN (E.SAL)>2000 THEN '2级'
ELSE '1级'
END
FROM EMP E;