1 子查询:

① 子查询嵌套在其它SQL语句内的select语句,且以括号()包裹;
② 子查询会优先执行,且结果作为外层主查询的过滤条件; 如:

select * from tab_name where column=(select column_2 from tab_name2);

示例1:身份证号’ 210210199901015555’用户,借了1本编号’ 20150301’图书,要求:更新读者信息表的余额。

update readerinfo set balance= balance-
	(select price from bookinfo where book_id = 20150301)*0.05
	where card_id = '210210199901015555';

示例2:查询borrowinfo表,显示《Spring源码深度解析》的借阅记录

select * from borrowinfo where book_id=(
	select book_id from bookinfo where book_name='Spring源码深度解析');

示例3:查询图书信息表,显示书价小于平均价格的所有图书

select * from bookinfo where price< (select avg(price) from bookinfo);

示例4:查询图书信息表,显示类别不是’数据库’的所有图书

select * from bookinfo where class_id !=(
	select class_id from bookclass where class_name ='数据库');

2 含 [not] in 操作符的子查询,如:

/*两查询结果相同*/
select * from tab_name where in(子查询);
select * from tab_name where =any(子查询);

in(子查询)的结果作为外层查询的条件,示例:

/* 显示图书别为‘医学’的所有图书信息 */
select * from bookinfo where class_id = any(select class_id from bookclass where parent_id=2);
select * from bookinfo where class_id in(select class_id from bookclass where parent_id=2);

/* 显示图书别不是‘医学’的所有图书信息 */
select * from bookinfo where class_id != any(select class_id from bookclass where parent_id=2);
select * from bookinfo where class_id not in(select class_id from bookclass where parent_id=2);

3 含 [not] exists 操作符的子查询,如:

select * from tab_name where exists(子查询);

判断子查询是否返回行:
① 返回结果, 则 exists 结果为 true, 外层 SQL 可执行;
② 无返回, 则 exists 结果为 false, 外层 SQL 不会执行;
not exists 子查询, 执行刚好相反;

4 插入记录时使用子查询,如:

insert into tab_name(column_list)(子查询);
/* 把子查询结果,插入到 tab_name数据表 */

示例:创建 逾期读者处罚信息表 readerfine,含book_id图书编号/ card_id证件编号/ return_date约定还书日/ actual_date实际还书日/ fine罚金。数据根据 borrowinfo 数据表 插入/更新:

/* 插入: 子查询结果 */
insert into readerfine(book_id, card_id, return_date) 
	select book_id, card_id, return_date from borrowinfo 
	where datediff(now(), return_date)>0 and status='否';

/* 更新 */
update borrowinfo set status='是' 
	where book_id=20151101 and card_id='210210199901012222';

update readerfine set actual_data = now(), 
	fine = datediff(now(), return_date) * 0.2
	where book_id=20151101 and card_id='210210199901012222';
create table readerfine(	/* 创建readerfine 数据表 */
	book_id int,
    card_id char(18),
    return_date date,
    actual_date date,
    fine decimal(7,2),
    primary key(book_id, card_id)
);

5 多表联接:inner join 内联接

据连接条件从多个表中选择数据,显示各表与连接条件匹配的数据行,组合为新记录;

select column_list 
	from tab_name [inner] join tab_1 on condition_1 [inner] join tab_2 on condition_2...
	where condition; /* [inner]关键字可省略 */

示例1:通过图书信息表和图书类别表,获得图书编号/名称/类别

select book_id,book_name,class_name 
	from bookinfo inner join bookclass on bookinfo.class_id=bookclass.class_id;

示例2: 借阅统计需要,查询未归还图书的编号/名称/身份证号/姓名/电话/归还日期/状态

select borrowinfo.book_id, book_name, borrowinfo.card_id, name,tel,return_date, status 
	from borrowinfo 
		inner join bookinfo on borrowinfo.book_id=bookinfo.book_id
		inner join readerinfo on borrowinfo.card_id=readerinfo.card_id
	where borrowinfo.status='否';
/* 或以 别名 简化代码; 并省略 inner关键字 */
select aa.book_id, book_name, aa.card_id, name, tel, return_date, status 
	from borrowinfo aa 
		join bookinfo bb on aa.book_id=bb.book_id
		join readerinfo cc on aa.card_id=cc.card_id
	where aa.status='否';

6 多表联接:[left | right] join 左/右外联接

select column_list 
	from tab_name left [outer] join tab_name2 on join_condition;
	where condition; /* 左外联接: 左表全部数据+右表的条件数据 */

select column_list 
	from tab_name right [outer] join tab_name2 on join_condition;
	where condition; /* 右外联接: 右表全部数据+左表的条件数据 */

示例:查看图书类别表中所有类别下都有哪些图书

select book_id, book_name, class_name 
	from bookclass left join bookinfo on bookclass.class_id=bookinfo.class_id
	where parent_id != 0; 	/* 以 left join 左外联接 实现 */

select book_id, book_name, class_name 
	from bookinfo right join bookclass on bookclass.class_id=bookinfo.class_id
	where parent_id != 0;	/* 以 right join 右外联接 实现 */

注意:对比两种实现方式中bookclass/ bookinfo两表的左/右位置差异

7 自联接:

① 联接查询中,涉及的多个表都是同1个表; ② 该表物理上为同1张表; 而逻辑上可分为2张表;
示例: 查询所有图书: 类别编号/ 名称/ 上级分类名称; 代码及查询结果 如下:

select a.class_id as'类别编号',a.class_name as'类别名称',b.class_name as'上级类名'
	from bookclass a left join bookclass b on a.parent_id=b.class_id;

类别编号

类别名称

上级别名

1

计算机

NULL

2

医学

NULL

3

编程语言

计算机

4

数据库

计算机

5

儿科学

医学

6

眼科学

医学

7

临床医学

医学

本例改以 [inner] join方式实现自联接; 及查询结果如下:

select a.class_id as'类别编号',a.class_name as'类别名称',b.class_name as'上级类名'
	from bookclass a join bookclass b on a.parent_id=b.class_id;

类别编号

类别名称

上级别名

3

编程语言

计算机

4

数据库

计算机

5

儿科学

医学

6

眼科学

医学

7

临床医学

医学