一、子查詢的基本理論
1.子查詢概念:
- ()
- 子查詢也叫做內部查詢,包含子查詢的語句稱為外部查詢或主查詢
2.子查詢的分類
- 非相關子查詢 --- 用的最多
- 子查詢的結果作為外部查詢的條件
- 子查詢的結果作為表
- 相關子查詢(關聯)
- 依賴於外部查詢的數據,外部查詢每執行一次,子查詢就執行一次
- 外部查詢先查詢,在執行子查詢
- 子查詢的結果作為列
- 依賴於外部查詢的數據,外部查詢每執行一次,子查詢就執行一次
案例:

如:第一題,建表
drop table if exists tb_lemon_score; create table tb_lemon_score( sname varchar(20), course varchar(20), score tinyint ); insert tb_lemon_score values ( '張三', '語文', 71 ), ( '張三', '數學', 75 ), ( '李四', '語文', 76 ), ( '李四', '數學', 90 ), ( '王五', '語文', 81 ), ( '王五', '數學', 100 ), ( '王五', '英語', 90 );
查詢:查詢出每門課程都大於80分的學生姓名
方式一
select sname,score from tb_lemon_score group by sname having min(score)>80;

方式二:子查詢的結果作為外部查詢的條件
先查詢出小於80的
select * from tb_lemon_score where sname not in (select sname from tb_lemon_score where score<=80);

方式三:子查詢的結果作為表
先查詢出每個人的最小成績,結果作為表,在查詢大於80分的學生
-- 每人的最小成績 select sname,min(score) 最小成績 from tb_lemon_score group by sname; -- 在結果中查詢 select * from (select sname,min(score) 最小成績 from tb_lemon_score group by sname) t where t.最小成績>80;


方式四:相關子查詢(關聯)
- 外部查詢先查詢,在執行子查詢
- EXISTS :運算符用於判斷查詢子句是否有記錄,如果有一條或多條記錄存在返回 True,否則返回 False
- not exists :EXISTS 可以與 NOT 一同使用,查找出不符合查詢語句的記錄:
select * from tb_lemon_score t1 where not exists (select * from tb_lemon_score t2 where t1.sname=t2.sname and t2.score<=80);

案例2:
#用sql語句查詢所有購入商品為兩種或兩種以上的購物人 -- 非關聯子查詢 SELECT sname FROM (SELECT sname,COUNT(merch) FROM shopping_list GROUP BY sname HAVING COUNT(merch)>=2) as list; -- 關聯子查詢 SELECT DISTINCT sname FROM shopping_list s1 WHERE EXISTS (SELECT * FROM shopping_list s2 WHERE s2.sname=s1.sname GROUP BY s2.sname HAVING COUNT(s2.merch)>=2)
面試題

1.查詢出所有語文成績超過平均水平的學生姓名、語文成績
-- 先兩條鏈接,1表id == 2表id 查詢后只有三條,and 語文成績大於平均成績 select s.name,sc.chinese from 表1 s,表2 sc where s.id = sc.id and sc.chinese > (select avg(chinese) from 表1); -- 相當於 inner join on select s.name,sc.chinese from 表1 s inner join 表2 sc on s.id = sc.id and sc.chinese > (select avg(chinese) from 表1);

2.查詢出所有學生的姓名、語文成績
select s.name,sc.chinese from 學生表1 s left join 成績表2 sc on s.id = sc.id;
======
-- 同上關聯子查詢,查詢結果作為列 select s.name,(select sc.chiinese from 成績表2 sc where 學生表.id = 成績表.id ) from 學生表1 s;
兩條結果都相同 
3.導出所有語文或數學成績大於90分的學生信息到exce1中
select s.name,sc.chinese,sc.math from 學生表1 s,成績表2 sc where s.id = sc.id and (sc.math>=90 or sc.chinese>=90);

-- 非相關子查詢,結果作為一張表 select s.*,t.* from 學生表 s,(select sc.* from 成績表 sc where sc.math>90 or sc.chinese>=90) t where s.id = t.id;

練習題:
1.建表及數據
-- 部門表 -- CREATE TABLE DEPT( DEPTNO INT PRIMARY KEY, -- 部門編號 DNAME VARCHAR(14) , -- 部門名稱 LOC VARCHAR(13) -- 部門地址 ) ; create table dept ( deptno int primary key, dname varchar ( 14 ), loc varchar ( 13 ) ); insert into dept values ( 10, 'accounting', 'new york' ); insert into dept values ( 20, 'research', 'dallas' ); insert into dept values ( 30, 'sales', 'chicago' ); insert into dept values ( 40, 'operations', 'boston' ); -- 員工表 -- CREATE TABLE EMP ( EMPNO INT PRIMARY KEY, -- 員工編號 ENAME VARCHAR(10), -- 員工名稱 JOB VARCHAR(9), -- 工作 MGR DOUBLE, -- 直屬領導編號 HIREDATE DATE, -- 入職時間 SAL DOUBLE, -- 工資 COMM DOUBLE, -- 獎金 DEPTNO INT, -- 部門號 FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO)); create table emp (empno int primary key,ename varchar (10),job varchar (9),mgr double,hiredate date,sal double,comm double,deptno int,foreign key (deptno) references dept (deptno)); insert into emp values ( 7369, 'smith', 'clerk', 7902, '1980-12-17', 800, null, 20 ); insert into emp values ( 7499, 'allen', 'salesman', 7698, '1981-02-20', 1600, 300, 30 ); insert into emp values ( 7521, 'ward', 'salesman', 7698, '1981-02-22', 1250, 500, 30 ); insert into emp values ( 7566, 'jones', 'manager', 7839, '1981-04-02', 2975, null, 20 ); insert into emp values ( 7654, 'martin', 'salesman', 7698, '1981-09-28', 1250, 1400, 30 ); insert into emp values ( 7698, 'blake', 'manager', 7839, '1981-05-01', 2850, null, 30 ); insert into emp values ( 7782, 'clark', 'manager', 7839, '1981-06-09', 2450, null, 10 ); insert into emp values ( 7788, 'scott', 'analyst', 7566, '1987-07-13', 3000, null, 20 ); insert into emp values ( 7839, 'king', 'president', null, '1981-11-17', 5000, null, 10 ); insert into emp values ( 7844, 'turner', 'salesman', 7698, '1981-09-08', 1500, 0, 30 ); insert into emp values ( 7876, 'adams', 'clerk', 7788, '1987-07-13', 1100, null, 20 ); insert into emp values ( 7900, 'james', 'clerk', 7698, '1981-12-03', 950, null, 30 ); insert into emp values ( 7902, 'ford', 'analyst', 7566, '1981-12-03', 3000, null, 20 ); insert into emp values ( 7934, 'miller', 'clerk', 7782, '1982-01-23', 1300, null, 10 );
2、根據emp和dept表完成下列作業:
-- 1.列出至少有三個員工的所有部門和部門信息。
SELECT dept.* from dept WHERE dept.DEPTNO IN (SELECT DEPTNO from emp GROUP BY emp.DEPTNO HAVING COUNT(emp.DEPTNO)>=3);

-- 2.列出受雇日期早於直接上級的所有員工的編號,姓名,部門名稱
SELECT e1.EMPNO, e1.ENAME,d.DNAME FROM emp e1,dept d WHERE e1.HIREDATE < (SELECT e2.HIREDATE FROM emp e2 WHERE e2.empno=e1.MGR) AND d.DEPTNO=e1.DEPTNO;

-- 3.列出職位為“CLERK”的姓名和部門名稱,部門人數:
SELECT emp_name,dept_name,emp_num FROM ( SELECT emp.ENAME emp_name, dept.DNAME dept_name, (SELECT COUNT(emp.EMPNO) FROM emp WHERE emp.DEPTNO=dept.DEPTNO) emp_num FROM emp,dept WHERE emp.JOB='CLERK' AND emp.DEPTNO=dept.DEPTNO ) as t

*******請大家尊重原創,如要轉載,請注明出處:轉載自:https://www.cnblogs.com/shouhu/,謝謝!!*******
