表关系
一对一(one to one) :每个实体的独有属性(区别于其他实体),如个人的邮箱,每个用户的邮箱都是不同的,即用户与邮箱之间的关系为一对一关系。用户与购物行为,因为多个用户都可以购物,则两者为多对一的关系。表与表之间有相同主键,即为一对一关系。
一对多(one to many):一个用户可以买多个商品,一个商品可以被多个用户购买,即多对多,需要一个用户表(主键:用户)和一个商品表(主键:不是用户),商品表的外键参考用户表的主键。
多对多(many to many):一个用户可以购买多个商品,一个商品可以被多个用户购买也可以被一个用户购买多次,这是就需要创建关联表,关联表是以两张表的主键建立,但是关联表的每列不需具有唯一性,类似于复合建,列合起来具有唯一性。
一对多 建表
员工表:emp
部门表:dept
create database day0902
;
use day0902
;
create table dept
(
did
int primary key,
dname
varchar(20);
)
create table emp
(
eid
int primary key,
ename
varchar(20),
eage
int,
dept_did
int,
sex
varchar(10),
foreign key(dept_did
) references dept
(did
)
)
1. 查询年纪最大的两个员工
select * from emp
order by eage
desc limit 0,2;
2. 查询年龄大于平均年龄的员工
select avg(eage
) from emp
;
select * from emp
where eage
> ( select avg(eage
) from emp
);
3. 查询年龄大于女员工平均年龄的男员工
select avg(eage
) from emp
where sex
= "女";
select * from emp
where sex
= "男" and (eage
> select avg(eage
) from emp
where sex
= "女");
4. 查询每个部门年龄最大的员工
select e
.ename
, e
.eage
, t
.dname
from emp
as e
, (select max(eage
) m
,dept_did dname
from emp
, dept
where did
= dept_did
group by dname
) as t
where e
.dept_did
= t
.dept_did
and e
.eage
= t
.m
;
多对多 建表(两个表和一个中间表)
课程表:
create database day0903
;
use day0903
;
create table sub
(
sid
int primary key,
sname
varchar(10)
);
学生表:
create table stu
(
sid
int primary key,
sname
varchar(10),
sage
int
);
中间表:
create table tb_stu_course
(
stid
int,
suid
int,
foreign key(stid
) references stu
(sid
),
foreign key(suid
) references course
(sid
)
)
1. 查询没有选择课程的学生
select * from
( select * from stu
left join tb_stu_sub ss
on stu
.sid
= ss
.stid
and suid
is null ) t
where stid
= null;
2. 查询选择人数最少的课程
select * from(
select count(sname
) c
, sname
from sub
, tb_stu_sub ss
where sub
.sid
= ss
.suid
group by sname
) tb1
where c
= (select min(c
) from (select count(sname
) c
, sname
from sub
, tb_stu_sub ss
where sub
.sid
= ss
.suid
group by sname
) tb2
);
3. 查询同时选了语文和数学的人
select a
, count(b
) c
from (
select stu
.sname a
, sub
.sname b
from stu
, tb_stu_sub ss
, sub
where stu
.sid
= ss
.stid
and sub
.sid
= ss
.suid
and (sub
.sname
= "语文" or sub
.sname
= "数学")) tb1
group by a
) tb2
where c
= 2;
);
4. 查询学生平均年龄最小的课程
select b
, avg(age
) av
from (
select stu
.sname a
, stu
.sage age
, sub
.sname b
from stu
, tb_stu_sub ss
, sub
where stu
.sid
= ss
.stid
and sub
. sid
= ss
.suid
) tb1
group by b
order by av
limit 0 , 1;
);