score
student
courses
inner join
内连接:查询的结果为两个表匹配到的数据
1.条件:查询学生信息及课程对应的分数
解析:此时信息存储在三张表通过外键标识,可以先将学生和分数表根据条件连接在一起,然后在连接课程
SELECT stu.studentno,sc.score,cs.name FROM test.students stu inner join test.scores sc on stu.studentNo=sc.studentno inner join test.courses cs on sc.courseNo=cs.courseNo
2.查询王昭君的成绩,要求显示姓名课程和分数
SELECT stu.name,sc.score,cs.name FROM test.students stu inner join test.scores sc on stu.studentNo=sc.studentno inner join test.courses cs on sc.courseNo=cs.courseNo
where stu.name='王昭君'
3.查询男生中的最高成绩 要求显示姓名 课程名 成绩
SELECT stu.sex,stu.name,sc.score,cs.name FROM test.students stu inner join test.scores sc on stu.studentNo=sc.studentno inner join test.courses cs on sc.courseNo=cs.courseNo
where sex='男' order by sc.score desc limit 1
left join
查询的结果为两张表匹配到的数据加左表特有的数据,对于右表中不存在的数据是用Null
1.条件:查询所有学生的成绩,包括没有成绩的学生
select * from test.students stu left join test. scores sc on stu.studentNo=sc.studentNo
2.查询所有学生的成绩,包括没有成绩的学生,需要显示课程名
select * from test.students stu left join test. scores sc on stu.studentNo=sc.studentNo left join test.courses cs on sc.courseNo=cs.courseNo
右连接
添加两门课程
insert into courses values
(0, '语文'),
(0, '数学');
例1:查询所有课程的成绩,包括没有成绩的课程
select
*
from
test.scores sc
right join test.courses cs on cs.courseNo = sc.courseNo
例2:查询所有课程的成绩,包括没有成绩的课程,包含学生信息
先把成绩和课程连接起来,以课程为主,连接起来之后看作一个整体,把这个整体再和学生信息表左连接
select
*
from
scores sc
right join courses cs on cs.courseNo = sc.courseNo
left join students stu on stu.studentNo = sc.studentNo
自关联
create table areas(
aid int primary key,
atitle varchar(20),
pid int
);
insert into areas
values ('130000', '河北省', NULL),
('130100', '石家庄市', '130000'),
('130400', '邯郸市', '130000'),
('130600', '保定市', '130000'),
('130700', '张家口市', '130000'),
('130800', '承德市', '130000'),
('410000', '河南省', NULL),
('410100', '郑州市', '410000'),
('410300', '洛阳市', '410000'),
('410500', '安阳市', '410000'),
('410700', '新乡市', '410000'),
('410800', '焦作市', '410000');
例1:查询一共有多少个省
注:统计个数,使用count(*) 尽量不要统计某一列,万一出现null会出错
select count(*) from areas where pid is null;
例1:查询河南省的所有城市
select * from test.areas p,test.areas c where p.aid=c.pid and where p.atitle='河南省'
select * from test.areas as p inner join test.areas as c on c.pid=p.aid where p.atitle='河北省';
例3:查询河南省的所有区县
select * from test.areas as p inner join test.areas as c on c.pid=p.aid inner join test.areas as q on c.aid=q.pid where p.atitle='河南省';
子查询
在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句
主查询和子查询的关系
- 子查询是嵌入到主查询中
- 子查询是辅助主查询的,要么充当条件,要么充当数据源
- 子查询是可以独立存在的语句,是一条完整的 select 语句
子查询分类
- 标量子查询: 子查询返回的结果是一个数据(一行一列)
- 列子查询: 返回的结果是一列(一列多行)
- 行子查询: 返回的结果是一行(一行多列)
- 表级子查询: 返回的结果是多行多列
标量子查询
例1:查询班级学生的平均年龄
查询班级学生平均年龄
select avg(age) from students
查询大于平均年龄的学生
select * from students where age > 21.4167
select * from students where age > (select avg(age) from students);
例2:查询王昭君的成绩,要求显示成绩
学生表中查询王昭君的学号
select studentNo from students where name = '王昭君'
成绩表中根据学号查询成绩
select * from scores where studentNo = '001'
select * from scores where studentNo = (select studentNo from students where name = '王昭君')
列级子查询v
返回一列多行
例3:查询18岁的学生的成绩,要求显示成绩
学生表中查询18岁的学生的学号
select studentNo from students where age=18
成绩表中根据学号查询成绩
select * from scores where studentNo in ('002','006')
select * from scores where studentNo in (select studentNo from students where age=18)
子查询中特定关键字使用
in 范围
- 格式: 主查询 where 条件 in (列子查询)
select * from students where age in (select age from students where age between 18 and 20)
any | some 任意一个
和in查询类似 等于范围内的任意一个
select * from test.students where age =any (select age from test.students where age between 18 and 20)
any等于some
select * from test.students where age =some (select age from test.students where age between 18 and 20)
# 大于其中的最小值 也就是大于18
select * from test.students where age >any (select age from test.students where age between 18 and 20)
# 小于范围内的最大值
select * from test.students where age <any (select age from test.students where age between 18 and 20)
# 小于里面的所有值 也就是小于最小值
select * from test.students where age <all (select age from test.students where age between 18 and 20)
# 大于其中所有值 也就是大于最大值
select * from test.students where age >all (select age from test.students where age between 18 and 20)
# 不等于范围所有值
select * from test.students where age !=all (select age from test.students where age between 18 and 20)
SQL演练
create table test.goods(
id int unsigned primary key auto_increment,
name varchar(150),
cate varchar(40),
brand_name varchar(40),
price decimal(10,3) default 0,
is_show bit default 1,
is_saleoff bit default 0
);
insert into test.goods values(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',default,default);
insert into test.goods values(0,'y400n 14.0英寸笔记本电脑','笔记本','联想','4999',default,default);
insert into test.goods values(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',default,default);
insert into test.goods values(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',default,default);
insert into test.goods values(0,'x240 超极本','超级本','联想','4999',default,default);
insert into test.goods values(0,'u330p 13.3英寸超极本','超级本','联想','4299',default,default);
insert into test.goods values(0,'svp13226scb 触控超极本','超级本','索尼','7999',default,default);
insert into test.goods values(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',default,default);
insert into test.goods values(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',default,default);
insert into test.goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default);
insert into test.goods values(0,'ideacentre c340 20英寸一体电脑 ','台式机','联想','3499',default,default);
insert into test.goods values(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',default,default);
insert into test.goods values(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',default,default);
insert into test.goods values(0,'at7-7414lp 台式电脑 linux )','台式机','宏碁','3699',default,default);
insert into test.goods values(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',default,default);
insert into test.goods values(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',default,default);
insert into test.goods values(0,'mac pro专业级台式电脑','服务器/工作站','苹果','28888',default,default);
insert into test.goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into test.goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
insert into test.goods values(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',default,default);
insert into test.goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into test.goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
求所有电脑产品的平均价格,并且保留两位小数
select round(avg(price),2) as avg_price from goods;
查询所有价格大于平均价格的商品,并且按价格降序排序
select id,name,price from goods
where price > (select round(avg(price),2) as avg_price from goods)
order by price desc;
查询类型为’超极本’的商品价格
select price from goods where cate = '超级本';
查询价格大于或等于"超级本"价格的商品,并且按价格降序排列
select id,name,price from test.goods
where price >= any(select price from test.goods where cate = '超级本')
order by price desc;
数据分表
该表设计的不合理
例如:分类和商品名称很多重复的,可以把这两个字段拿出来单独存放
比如我现在想把联想改成thinkpad 那就需要去原表把所有的联想都改了,但是单独拿出来保存其主见只需要改一个就行
创建“商品分类”表
create table if not exists goods_cates(
cate_id int unsigned primary key auto_increment,
cate_name varchar(40)
);
查询goods表的所有记录,并且按"类别"分组
select cate from goods group by cate;
查询goods表的所有记录,并且按"类别"分组
select cate from goods group by cate;
select distinct from goods ;
将分组结果写入到goods_cates数据表
insert into goods_cates (cate_name) select cate from goods group by cate;
通过create…select来创建数据表并且同时写入记录,一步到位
字段名称要对应
create table goods_brands (
brand_id int unsigned primary key auto_increment,
brand_name varchar(40)) select brand_name from goods group by brand_name;
注:也可以用该命令对表进行被封
create table goods_back select * from goods
此时需要将Goods表的商品名称改成id
通过goods_brands数据表来更新goods数据表
update goods as g inner join goods_brands as b on g.brand_name = b.brand_name
set g.brand_name = b.brand_id;
update test.goods g inner join test.goods_cates c on g.cate = c.cate_name set g.cate = c.cate_id;
查看 goods 的数据表结构,会发现 cate 和 brand_name对应的类型为 varchar 但是存储的都是字符串
修改数据表结构,把cate字段改为cate_id且类型为int unsigned,把brand_name字段改为brand_id且类型为int unsigned
查询所有商品的详细信息 (通过内连接)
通过两张表的品牌ID进行内连接后生成一张表
通过新生成的1表和2表关联生产3表 这样就可以查询到完整的商品表了
查询所有商品的详细信息 (通过内连接)
select id,name,cate_name,brand_name,price from goods as g
inner join goods_cates as c on g.cate_id = c.cate_id
inner join goods_brands as b on g.brand_id = b.brand_id;
在 goods 数据表中写入任意记录
insert into goods (name,cate_id,brand_id,price)
values('LaserJet Pro P1606dn 黑白激光打印机','12','4','1849');
查询所有商品的详细信息 (通过左连接)
select id,name,cate_name,brand_name,price from goods as g
left join goods_cates as c on g.cate_id = c.cate_id
left join goods_brands as b on g.brand_id = b.brand_id;