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 | 临床医学 | 医学 |