01返回单行的子查询
SELECT STU.* FROM STU WHERE AGE = (SELECT AGE FROM STU WHERE NAME = '林琳');
SELECT STU.* FROM STU WHERE AGE >= (SELECT AVG(AGE) FROM STU);
SELECT * FROM STU WHERE NO = (SELECT NO FROM GRADE WHERE SCORE = 85); --OR SELECT S.* FROM STU S INNER JOIN GRADE G ON S.NO = G.NO WHERE G.SCORE = 85; --使用单行子查询时,一定要确认子查询只能返回单个值 --否则使用>,<,=,>=,<=,<>运算符将会报错
02用IN实现多行子查询
SELECT STU.* FROM STU WHERE DEPT IN(SELECT DEPT FROM STU WHERE NAME = '陈诚'); SELECT STU.* FROM STU WHERE NO NOT IN(SELECT NO FROM GRADE WHERE SCORE < 90) AND NO IN(SELECT NO FROM GRADE); --OR SELECT STU.*, GRADE.* FROM STU INNER JOIN GRADE ON STU.NO = GRADE.NO WHERE GRADE.SCORE > 90; --如果能用子查询一般用子查询取代连接查询,子查询可读性更强效率更高
03EXISTS子查询
SELECT STU.* FROM STU WHERE EXISTS(SELECT 1 FROM GRADE WHERE NO = STU.NO AND NAME = '计算机基础'); --EXISTS判断子查询返回值,如果为空则返回false,否则返回true --执行流程: --在stu中依次取出每条记录的no值,用改制去检查表grade的where条件 --如果grade表中存在no=stu.no并且name='计算机基础'的记录, --EXISTS返回true并取此记录的no对应的stu的记录 --依次循环,一直到stu表中所有记录比较完成
SELECT STU.* FROM STU WHERE NOT EXISTS(SELECT 1 FROM GRADE WHERE NO = STU.NO AND NAME = '计算机基础');
04EXISTS代替单行子查询
SELECT S1.* FROM STU S1 WHERE EXISTS(SELECT 1 FROM STU S2 WHERE S1.AGE = S2.AGE AND S2.NAME = '林琳'); --OR SELECT STU.* FROM STU WHERE AGE = (SELECT AGE FROM STU WHERE NAME = '林琳');
05含聚合函数的相关子查询
SELECT STU.* FROM STU WHERE 1 = (SELECT COUNT(*) FROM GRADE WHERE NO = STU.NO);
06带IN的相关子查询
SELECT STU.* FROM STU WHERE '计算机基础' IN (SELECT NAME FROM GRADE WHERE NO = STU.NO);
07包含分组的相关子查询
SELECT DEPT, AVG(AGE) FROM STU S1 GROUP BY S1.DEPT HAVING AVG(AGE) < ANY(SELECT AGE FROM STU S2 WHERE S1.DEPT = S2.DEPT); --ANY表示任意个,小于任意一个即可符合条件 --分组年龄平均值小于分组内任意个年龄即符合条件 --相关子查询中子查询的查询条件依赖与外层父查询的某个列值并依次执行 --执行效率一般低于连接查询,但子查询的性能完全依赖于查询和有关数据。
09带ALL的子查询
SELECT STU.* FROM STU WHERE DEPT <>'12计算机' AND AGE < ALL(SELECT AGE FROM STU WHERE DEPT = '12计算机'); -- ALL表示所有值比较并都满足条件才为true;ANY 表示任意值满足即条件成立
10嵌套子查询
SELECT STU.* FROM STU WHERE NO IN(SELECT NO FROM GRADE WHERE NAME IN (SELECT NAME FROM COURSE WHERE SCORE = 4)) AND DEPT = '12计算机' ORDER BY AGE DESC; --ORACLE支持的嵌套层次最多为255,应尽量多层嵌套,使用表连接查询性能可能会更高
11FROM子句后的子查询
SELECT * FROM(SELECT * FROM STU WHERE AGE >22); --FROM子查询经常在做临时表中使用
12SELECT子句后的子查询
SELECT STU.*,(SELECT SYSDATE FROM DUAL) FROM STU; --SELECT子句中使用子查询时一定要保证是单行返回值子查询才能成功执行
13HAVING子句后的子查询
SELECT DEPT ,COUNT(1) FROM STU GROUP BY DEPT HAVING DEPT IN (SELECT DEPT FROM STU WHERE AGE>22)
14子查询返回空值
SELECT STU.* FROM STU WHERE DEPT = (SELECT DEPT FROM STU WHERE AGE < 20) ORDER BY NO --子查询查询结果集为null,将导致父查寻结果集也为NULL
DROP TABLE EMP CASCADE CONSTRAINTS; CREATE TABLE EMP ( EMPNO NUMBER(4), ENAME VARCHAR2(10 BYTE), JOB VARCHAR2(9 BYTE), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2) ); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7369, 'SMITH', 'CLERK', 7902, TO_DATE('1980/12/17', 'YYYY/MM/DD'), 800, 20); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) Values (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('1981/2/20', 'YYYY/MM/DD'), 1600, 300, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) Values (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('1981/2/22', 'YYYY/MM/DD'), 1250, 500, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7566, 'JONES', 'MANAGER', 7839, TO_DATE('1981/4/2', 'YYYY/MM/DD'), 2975, 20); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) Values (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('1981/9/28', 'YYYY/MM/DD'), 1250, 1400, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('1981/5/1', 'YYYY/MM/DD'), 2850, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('1981/6/9', 'YYYY/MM/DD'), 2450, 10); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('1982/12/9', 'YYYY/MM/DD'), 3000, 20); Insert into EMP (EMPNO, ENAME, JOB, HIREDATE, SAL, DEPTNO) Values (7839, 'KING', 'PRESIDENT', TO_DATE('1981/11/17', 'YYYY/MM/DD'), 5000, 10); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) Values (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('1981/9/8', 'YYYY/MM/DD'), 1500, 0, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('1983/1/12', 'YYYY/MM/DD'), 1100, 20); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7900, 'JAMES', 'CLERK', 7698, TO_DATE('1981/12/3', 'YYYY/MM/DD'), 950, 30); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7902, 'FORO', 'ANALYST', 7566, TO_DATE('1981/12/3', 'YYYY/MM/DD'), 3000, 20); Insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) Values (7934, 'MILLER', 'CLERK', 7782, TO_DATE('1982/1/23', 'YYYY/MM/DD'), 1300, 10); COMMIT; DROP TABLE GRADE CASCADE CONSTRAINTS; CREATE TABLE GRADE ( NO VARCHAR2(10 BYTE) NOT NULL, NAME VARCHAR2(10 BYTE), SCORE NUMBER ); Insert into GRADE (NO, NAME, SCORE) Values ('120001', '计算机基础', 85); Insert into GRADE (NO, NAME, SCORE) Values ('120003', '计算机基础', 96); Insert into GRADE (NO, NAME, SCORE) Values ('120004', '计算机基础', 60); COMMIT; DROP TABLE COURSE CASCADE CONSTRAINTS; CREATE TABLE COURSE( NAME VARCHAR2(20), SCORE NUMBER ); INSERT INTO COURSE VALUES('计算机基础', 4); INSERT INTO COURSE VALUES('数据结构', 4); INSERT INTO COURSE VALUES('计算机英语', 2); COMMIT; DROP TABLE GROUP_BY_TEST CASCADE CONSTRAINTS; CREATE TABLE GROUP_BY_TEST ( NAME VARCHAR2(20 BYTE), CLASS VARCHAR2(20 BYTE), ITEM VARCHAR2(20 BYTE), OBJECT VARCHAR2(20 BYTE), PRICE NUMBER ); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', '3C', 'phone', 'huawei', 4000); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', '3C', 'phone', 'xiaomi', 3000); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', '3C', 'computer', 'mac', 10000); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', '3C', 'phone', 'thinkpad', 8000); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', '3C', 'phone', 'huawei', 4000); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', 'clothes', 'shoes', 'adidas', 300); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', 'clothes', 'shoes', 'lining', 400); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('springy', 'clothes', 'pants', 'jackjones', 500); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('stephenson', 'clothes', 'shoes', 'adivon', 200); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('stephenson', 'clothes', 'shoes', 'nike', 300); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('stephenson', 'clothes', 'skirt', 'nike', 300); Insert into GROUP_BY_TEST (NAME, CLASS, ITEM, OBJECT, PRICE) Values ('stephenson', 'clothes', 'skirt', 'adidas', 400); COMMIT;