关系连接查询

 

高级 关系 连接

 
复制代码
select distinct 列*
from 表1 innser|left|right join 表2 on 表1与表2的关系
where ...
group by ... (5个聚合函数,avg,max,sum,min,count)
having ...
order by ... (排序desc|asc)
limit start,count
复制代码

1.关系

  • 创建成绩表scores,结构如下
    • id
    • 学生
    • 科目
    • 成绩
  • 思考:学生列应该存什么信息呢?
  • 答:学生列的数据不是在这里新建的,而应该从学生表引用过来,关系也是一条数据;根据范式要求应该存储学生的编号,而不是学生的姓名等其它信息
  • 同理,科目表也是关系列,引用科目表中的数据

    

2.外键约束

  • 思考:怎么保证关系列数据的有效性呢?任何整数都可以吗?
  • 答:必须是学生表中id列存在的数据,可以通过外键约束进行数据的有效性验证
  • 为stuid添加外键约束
alter table scores add constraint stu_sco foreign key(stuid) references students(id);
  • 在创建表时可以直接创建约束
复制代码
create table scores(
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2),
foreign key(stuid) references students(id),
foreign key(subid) references subjects(id)
);
复制代码
复制代码
mysql> create table scores(
    -> id int auto_increment primary key not null,
    -> score decimal(4,1),
    -> stuid int,
    -> subid int,
    -> foreign key(stuid) references students(id),
    -> foreign key(subid) references subjects(id));
复制代码
  • 添加数据
复制代码
mysql> insert into scores values(0,100,1,1);
Query OK, 1 row affected (0.01 sec)

mysql> select * from scores;
+----+-------+-------+-------+
| id | score | stuid | subid |
+----+-------+-------+-------+
|  1 | 100.0 |     1 |     1 |
+----+-------+-------+-------+
复制代码
mysql> insert into scores values(0,100,10,10);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`py31`.`scores`, CONSTRAINT `scores_ibfk_2` FOREIGN KEY (`subid`) REFERENCES `subjects` (`id`))

3.外键的级联操作()逻辑删除

  • 在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常
  • 推荐使用逻辑删除,还可以解决这个问题
  • 可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作

级联操作的类型包括:

  • restrict(限制):默认值,抛异常
  • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除
  • set null:将外键设置为空
  • no action:什么都不做
alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;

4.连接查询

  • 问:查询每个学生每个科目的分数
  • 分析:学生姓名来源于students表,科目名称来源于subjects,分数来源于scores表,怎么将3个表放到一起查询,并将结果显示在同一个结果集中呢?
  • 答:当查询结果来源于多张表时,需要使用连接查询
  • 关键:找到表间的关系,当前的关系是
    • students表的id---scores表的stuid
    • subjects表的id---scores表的subid
  • 则上面问题的答案是:
select students.sname,subjects.stitle,scores.score
from scores
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id;

  1)查询成绩

复制代码
mysql> select * from scores;
+----+-------+-------+-------+
| id | score | stuid | subid |
+----+-------+-------+-------+
|  1 | 100.0 |     1 |     1 |
|  3 | 100.0 |     3 |     2 |
|  4 | 100.0 |     4 |     5 |
|  5 |  94.0 |     3 |     5 |
|  6 |  94.0 |     7 |     5 |
|  7 |  92.0 |     7 |     5 |
|  8 |  92.0 |     8 |     5 |
|  9 |  72.0 |     8 |     5 |
+----+-------+-------+-------+
复制代码

  2)连接查询

复制代码
学生表 - 班级表

郭靖 python 100
student.name  
subjects.title
scores.score

select students.name,subjects.title,scores.score 
from scores 
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id;
复制代码
复制代码
+-----------+---------+-------+
| name      | title   | score |
+-----------+---------+-------+
| 腾旭      | python  | 100.0 |
| 网易      | linux   | 100.0 |
| 小米      | mysqlDB | 100.0 |
| 网易      | mysqlDB |  94.0 |
| QQ        | mysqlDB |  94.0 |
| QQ        | mysqlDB |  92.0 |
| 腾讯云    | mysqlDB |  92.0 |
| 腾讯云    | mysqlDB |  72.0 |
+-----------+---------+-------+
复制代码
  • 表A inner join 表B:表A与表B匹配的行会出现在结果中
select *
from students inner join scores 
on students.id=scores.stuid
  • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
select *
from students left join scores 
on students.id=scores.stuid
复制代码
mysql> mysql> select * from students left join scores  on students.id=scores.stuid;
+----+-----------+--------+---------------------+----------+------+-------+-------+-------+
| id | name      | gender | birthday            | isDelete | id   | score | stuid | subid |
+----+-----------+--------+---------------------+----------+------+-------+-------+-------+
|  1 | 腾旭      |       | 1999-09-09 00:00:00 |          |    1 | 100.0 |     1 |     1 |
|  3 | 网易      |       | NULL                |          |    3 | 100.0 |     3 |     2 |
|  4 | 小米      |       | NULL                |          |    4 | 100.0 |     4 |     5 |
|  3 | 网易      |       | NULL                |          |    5 |  94.0 |     3 |     5 |
|  7 | QQ        |       | NULL                |          |    6 |  94.0 |     7 |     5 |
|  7 | QQ        |       | NULL                |          |    7 |  92.0 |     7 |     5 |
|  8 | 腾讯云    |       | NULL                |          |    8 |  92.0 |     8 |     5 |
|  8 | 腾讯云    |       | NULL                |          |    9 |  72.0 |     8 |     5 |
|  2 | 腾旭      |       | 1990-02-02 00:00:00 |          | NULL |  NULL |  NULL |  NULL |
|  6 | 酷狗      |        | 2017-02-13 00:00:00 |         | NULL |  NULL |  NULL |  NULL |
|  9 | 华为      |       | NULL                |          | NULL |  NULL |  NULL |  NULL |
| 10 | 京东      |       | NULL                |          | NULL |  NULL |  NULL |  NULL |
| 11 | 微博      |       | NULL                |          | NULL |  NULL |  NULL |  NULL |
| 12 | 微信      |       | NULL                |          | NULL |  NULL |  NULL |  NULL |
+----+-----------+--------+---------------------+----------+------+-------+-------+-------+
复制代码
  • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充
select *
from  scores right join students
on students.id=scores.stuid
复制代码
+------+-------+-------+-------+----+-----------+--------+---------------------+----------+
| id   | score | stuid | subid | id | name      | gender | birthday            | isDelete |
+------+-------+-------+-------+----+-----------+--------+---------------------+----------+
|    1 | 100.0 |     1 |     1 |  1 | 腾旭      |       | 1999-09-09 00:00:00 |          |
|    3 | 100.0 |     3 |     2 |  3 | 网易      |       | NULL                |          |
|    4 | 100.0 |     4 |     5 |  4 | 小米      |       | NULL                |          |
|    5 |  94.0 |     3 |     5 |  3 | 网易      |       | NULL                |          |
|    6 |  94.0 |     7 |     5 |  7 | QQ        |       | NULL                |          |
|    7 |  92.0 |     7 |     5 |  7 | QQ        |       | NULL                |          |
|    8 |  92.0 |     8 |     5 |  8 | 腾讯云    |       | NULL                |          |
|    9 |  72.0 |     8 |     5 |  8 | 腾讯云    |       | NULL                |          |
| NULL |  NULL |  NULL |  NULL |  2 | 腾旭      |       | 1990-02-02 00:00:00 |          |
| NULL |  NULL |  NULL |  NULL |  6 | 酷狗      |        | 2017-02-13 00:00:00 |         |
| NULL |  NULL |  NULL |  NULL |  9 | 华为      |       | NULL                |          |
| NULL |  NULL |  NULL |  NULL | 10 | 京东      |       | NULL                |          |
| NULL |  NULL |  NULL |  NULL | 11 | 微博      |       | NULL                |          |
| NULL |  NULL |  NULL |  NULL | 12 | 微信      |       | NULL                |          |
+------+-------+-------+-------+----+-----------+--------+---------------------+----------+
复制代码

5.练习

  • 查询学生的姓名、平均分
复制代码
mysql> select stuid,avg(score) from scores group by stuid;
+-------+------------+
| stuid | avg(score) |
+-------+------------+
|     1 |  100.00000 |
|     3 |   97.00000 |
|     4 |  100.00000 |
|     7 |   93.00000 |
|     8 |   82.00000 |
+-------+------------+
复制代码
复制代码
mysql> select stuid,avg(score) from scores  inner join students on  scores.stuid=students.id group by stuid;
+-------+------------+
| stuid | avg(score) |
+-------+------------+
|     1 |  100.00000 |
|     3 |   97.00000 |
|     4 |  100.00000 |
|     7 |   93.00000 |
|     8 |   82.00000 |
+-------+------------+
复制代码
复制代码
mysql> select name,stuid,avg(score) from scores  inner join students on  scores.stuuid=students.id group by stuid;
+-----------+-------+------------+
| name      | stuid | avg(score) |
+-----------+-------+------------+
| 腾旭      |     1 |  100.00000 |
| 网易      |     3 |   97.00000 |
| 小米      |     4 |  100.00000 |
| QQ        |     7 |   93.00000 |
| 腾讯云    |     8 |   82.00000 |
+-----------+-------+------------+
5 rows in set (0.00 sec)
复制代码
复制代码
mysql> select name,avg(score) from scores  inner join students on  scores.stuid=students.id group by stuid;
+-----------+------------+
| name      | avg(score) |
+-----------+------------+
| 腾旭      |  100.00000 |
| 网易      |   97.00000 |
| 小米      |  100.00000 |
| QQ        |   93.00000 |
| 腾讯云    |   82.00000 |
+-----------+------------+
复制代码
复制代码
mysql> select name,avg(score) from scores  inner join students on  scores.stuid=students.id group by stuid order by avg(score) desc;
+-----------+------------+
| name      | avg(score) |
+-----------+------------+
| 小米      |  100.00000 |
| 腾旭      |  100.00000 |
| 网易      |   97.00000 |
| QQ        |   93.00000 |
| 腾讯云    |   82.00000 |
+-----------+------------+
复制代码
  • 查询男生的姓名、总分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
where students.gender=1
group by students.sname;

     

查询男生的姓名、总分
students.gender=1
students.name 
sum(scores.score)
建立连接:students.id=scores.stuid 
使用sum 聚合 --》 分组 group by 姓名:每个人的总分
select name,sum(score) 
from students
inner join scores on students.id=scores.stuid
where gender=1 
group by name   
group by students.id  (如果同名)
  • 查询科目的名称、平均分
select subjects.stitle,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.stitle;
复制代码
查询科目的名称、平均分
subjects.tilte
avg(scores.score)

建立连接:subjects.id=scores.subid
使用avg ---》 group by subjects.title 

select subjects.title,avg(scores.score)
from scores
inner join subjects on subjects.id=scores.subid
group by subjects.title
复制代码
  • 查询未删除科目的名称、最高分、平均分
select subjects.stitle,avg(scores.score),max(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
where subjects.isdelete=0
group by subjects.stitle;
复制代码
查询未删除科目的名称、最高分、平均分
where subjects.isDelete=0
subjects.tilte
max(scores.score)
avg(scores.score)

建立连接subjects.id=scores.subid
max avg --> group by subjects.tilte

select subjects.title,max(scores.score),avg(scores.score)
from subjects
inner join scores on  subjects.id=scores.subid
where subjects.isDelete=0
group by subjects.title
复制代码
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/Bighua123/p/8108212.html