美文网首页
MySQL-子查询及连接

MySQL-子查询及连接

作者: abona | 来源:发表于2019-07-11 16:32 被阅读0次

子查询

当一个查询是另一个查询的条件时,称之为子查询。

  • 子查询必须用括号括起来。
    由比较运算符引发的子查询:
    先新建一个数据表
CREATE TABLE students (
    id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    class_name VARCHAR(20) NOT NULL,
    teacher_name VARCHAR(20) NOT NULL,
    score SMALLINT UNSIGNED
);
-- 插入几条数据
INSERT INTO students VALUES 
(NULL,'张山','网络18-1班','陈老师',78), 
(NULL,'王五','微机18-1班','张老师',85),
(NULL,'赵六','设计18-1班','林老师',66),
(NULL,'陈七','网络18-1班','陈老师',90),
(NULL,'阿狗','电子18-1班','王老师',88),
(NULL,'狗腿','电子18-1班','王老师',95),
(NULL,'陈七','网络18-1班','陈老师',90),
(NULL,'小咪','设计18-1班','林老师',98),
(NULL,'富贵','微机18-1班','张老师',83),
(NULL,'王五','微机18-1班','张老师',85);

现在查出他们的平均成绩

SELECT ROUND(AVG(score),1) FROM students;
+---------------------+
| ROUND(AVG(score),1) |
+---------------------+
|                85.8 |
+---------------------+

查出比平均成绩高的学生

SELECT * FROM students WHERE score > (SELECT ROUND(AVG(score),1) FROM students);
+----+--------+---------------+--------------+-------+
| id | name   | class_name    | teacher_name | score |
+----+--------+---------------+--------------+-------+
|  4 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  5 | 阿狗   | 电子18-1班    | 王老师       |    88 |
|  6 | 狗腿   | 电子18-1班    | 王老师       |    95 |
|  7 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  8 | 小咪   | 设计18-1班    | 林老师       |    98 |
+----+--------+---------------+--------------+-------+

ANY SOME ALL关键字

对子查询中返回的多行结果进行处理

··· ANY SOME ALL
>、>= 最小值 最小值 最大值
<、<= 最大值 最大值 最小值
= 任意值 任意值
<>、!= 最大值

使用: 查询

-- 先查询下林老师学生的分数
SELECT score FROM students WHERE teacher_name = '林老师';
+-------+
| score |
+-------+
|    66 |
|    98 |
+-------+
-- 找出比林老师学生分数高的学生
SELECT * FROM students 
WHERE score > (SELECT score FROM students WHERE teacher_name = '林老师');
-- 不使用关键字时会报错
-- ERROR 1242 (21000): Subquery returns more than 1 row
-- 返回结果超过一行,不知道该跟那个做对比了
-- 使用关键字, 图标中可以看到,使用 ‘>’ ANY会跟返回结果中值最小的对比 最小的分数为66
SELECT * FROM students 
WHERE score > ANY (SELECT score FROM students WHERE teacher_name = '林老师');
+----+--------+---------------+--------------+-------+
| id | name   | class_name    | teacher_name | score |
+----+--------+---------------+--------------+-------+
|  1 | 张山   | 网络18-1班    | 陈老师       |    78 |
|  2 | 王五   | 微机18-1班    | 张老师       |    85 |
|  4 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  5 | 阿狗   | 电子18-1班    | 王老师       |    88 |
|  6 | 狗腿   | 电子18-1班    | 王老师       |    95 |
|  7 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  8 | 小咪   | 设计18-1班    | 林老师       |    98 |
|  9 | 富贵   | 微机18-1班    | 张老师       |    83 |
| 10 | 王五   | 微机18-1班    | 张老师       |    85 |
+----+--------+---------------+--------------+-------+
-- 使用 ‘<’ ANY会跟最大的对比,最大分为98
SELECT * FROM students 
WHERE score < ANY (SELECT score FROM students WHERE teacher_name = '林老师');
+----+--------+---------------+--------------+-------+
| id | name   | class_name    | teacher_name | score |
+----+--------+---------------+--------------+-------+
|  1 | 张山   | 网络18-1班    | 陈老师       |    78 |
|  2 | 王五   | 微机18-1班    | 张老师       |    85 |
|  3 | 赵六   | 设计18-1班    | 林老师       |    66 |
|  4 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  5 | 阿狗   | 电子18-1班    | 王老师       |    88 |
|  6 | 狗腿   | 电子18-1班    | 王老师       |    95 |
|  7 | 陈七   | 网络18-1班    | 陈老师       |    90 |
|  9 | 富贵   | 微机18-1班    | 张老师       |    83 |
| 10 | 王五   | 微机18-1班    | 张老师       |    85 |
+----+--------+---------------+--------------+-------+

多表更新

-- 新建班级表
CREATE TABLE classes(
class_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
class_name VARCHAR(20) NOT NULL,
teacher_name VARCHAR(20) NOT NULL
);
/
-- 将学生表的班级及老师写入班级表
INSERT classes (class_name,teacher_name)
SELECT class_name,teacher_name 
FROM students GROUP BY class_name;
-- 查询结果
SELECT * FROM classes;
+----------+---------------+--------------+
| class_id | class_name    | teacher_name |
+----------+---------------+--------------+
|        1 | 微机18-1班    | 张老师       |
|        2 | 电子18-1班    | 王老师       |
|        3 | 网络18-1班    | 陈老师       |
|        4 | 设计18-1班    | 林老师       |
+----------+---------------+--------------+
-- 正文
-- 将学生表班级名更改成班级id
UPDATE students INNER JOIN (SELECT class_id,class_name FROM classes ) AS cl
ON students.class_name = cl.class_name SET students.class_name = cl.class_id; 
-- 查看结果
+----+--------+------------+--------------+-------+
| id | name   | class_name | teacher_name | score |
+----+--------+------------+--------------+-------+
|  1 | 张山   | 1          | 陈老师       |    78 |
|  2 | 王五   | 2          | 张老师       |    85 |
|  3 | 赵六   | 3          | 林老师       |    66 |
|  4 | 陈七   | 1          | 陈老师       |    90 |
|  5 | 阿狗   | 4          | 王老师       |    88 |
|  6 | 狗腿   | 4          | 王老师       |    95 |
|  7 | 陈七   | 1          | 陈老师       |    90 |
|  8 | 小咪   | 3          | 林老师       |    98 |
|  9 | 富贵   | 2          | 张老师       |    83 |
| 10 | 王五   | 2          | 张老师       |    85 |
+----+--------+------------+--------------+-------+
-- 另一种方法
-- 建表时直接写入
CREATE TABLE teachers (
teacher_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
teacher_name VARCHAR(20) NOT NULL
)
SELECT teacher_name  FROM students GROUP BY teacher_name;
-- 然后更新
UPDATE students INNER JOIN (SELECT * FROM  teachers) 
AS  t ON students.teacher_name = t.teacher_name 
SET students.teacher_name = t.teacher_id;
-- 最后更改下学生表字段名
ALTER TABLE students CHANGE class_name class_id SMALLINT 
UNSIGNED  NOT NULL;
ALTER TABLE students CHANGE teacher_name teacher_id SMALLINT UNSIGNED NOT NULL;

连接

内连接的连接查询结果集中仅包含满足条件的行,外连接(左、右)的连接查询结果集中既包含那些满足条件的行,还包含其中某个表的全部行

1、内连接

-- 写入两条数据
INSERT INTO students VALUES (NULL,'张伟','10','12',100),
(NULL,'刘六','12','10',100);
INSERT INTO classes VALUE (NULL,'机电18-1班','潘老师');
-- 连接查询
-- 显示班级
SELECT id,name,cl.class_name FROM students 
INNER JOIN classes AS cl ON students.class_id = cl.class_id;
+----+--------+---------------+
| id | name   | class_name    |
+----+--------+---------------+
|  1 | 张山   | 网络18-1班    |
|  2 | 王五   | 微机18-1班    |
|  3 | 赵六   | 设计18-1班    |
|  4 | 陈七   | 网络18-1班    |
|  5 | 阿狗   | 电子18-1班    |
|  6 | 狗腿   | 电子18-1班    |
|  7 | 陈七   | 网络18-1班    |
|  8 | 小咪   | 设计18-1班    |
|  9 | 富贵   | 微机18-1班    |
| 10 | 王五   | 微机18-1班    |
+----+--------+---------------+
-- 里面没有张伟跟刘六,是因为他们不符合条件 
-- 张伟和刘六的class_id 为10,12
+----------+---------------+--------------+
| class_id | class_name    | teacher_name |
+----------+---------------+--------------+
|        1 | 微机18-1班    | 张老师       |
|        2 | 电子18-1班    | 王老师       |
|        3 | 网络18-1班    | 陈老师       |
|        4 | 设计18-1班    | 林老师       |
|        5 | 机电18-1班    | 潘老师       |
+----------+---------------+--------------+
-- 表里是没有这两个class_id的,所以不会显示
-- 同理 没有学生的class_id为5,所以也不符合条件

2、左连接

-- 还是查询班级
SELECT id,name,cl.class_name FROM students 
LEFT JOIN classes AS cl ON students.class_id = cl.class_id;
+----+--------+---------------+
| id | name   | class_name    |
+----+--------+---------------+
|  2 | 王五   | 微机18-1班    |
|  9 | 富贵   | 微机18-1班    |
| 10 | 王五   | 微机18-1班    |
|  5 | 阿狗   | 电子18-1班    |
|  6 | 狗腿   | 电子18-1班    |
|  1 | 张山   | 网络18-1班    |
|  4 | 陈七   | 网络18-1班    |
|  7 | 陈七   | 网络18-1班    |
|  3 | 赵六   | 设计18-1班    |
|  8 | 小咪   | 设计18-1班    |
| 11 | 张伟   | NULL          |
| 12 | 刘六   | NULL          |
+----+--------+---------------+
-- 左连接说明JOIN左侧的所有记录均会被显示,无论其在右侧是否得到匹配
-- 刘六 张伟 没有班级,会显示为NULL

3、右连接

SELECT id,name,cl.class_name FROM students 
RIGHT JOIN classes AS cl ON students.class_id = cl.class_id;
+------+--------+---------------+
| id   | name   | class_name    |
+------+--------+---------------+
|    1 | 张山   | 网络18-1班    |
|    2 | 王五   | 微机18-1班    |
|    3 | 赵六   | 设计18-1班    |
|    4 | 陈七   | 网络18-1班    |
|    5 | 阿狗   | 电子18-1班    |
|    6 | 狗腿   | 电子18-1班    |
|    7 | 陈七   | 网络18-1班    |
|    8 | 小咪   | 设计18-1班    |
|    9 | 富贵   | 微机18-1班    |
|   10 | 王五   | 微机18-1班    |
| NULL | NULL   | 机电18-1班    |
+------+--------+---------------+

-- 右连接说明JOIN右侧的所有记录均会被显示,无论其在左侧是否得到匹配
-- 机电18-1班没有学生,会显示为NULL

无限级分类

-- 新建省份城市表
CREATE TABLE areas (
id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
area_name VARCHAR(30) NOT NULL,
parent_id SMALLINT UNSIGNED NOT NULL
);
-- 写入一些数据
INSERT INTO areas VALUES 
(NULL,'广东省',0),
(NULL,'江苏省',0),
(NULL,'山东省',0),
(NULL,'浙江省',0),
(NULL,'河南省',0),
(NULL,'广州市',1),
(NULL,'深圳市',1),
(NULL,'南京市',2),
(NULL,'济南市',3),
(NULL,'青岛市',3),
(NULL,'杭州市',4),
(NULL,'宁波市',4),
(NULL,'郑州市',5);

+----+-----------+-----------+
| id | area_name | parent_id |
+----+-----------+-----------+
|  1 | 广东省    |         0 |
|  2 | 江苏省    |         0 |
|  3 | 山东省    |         0 |
|  4 | 浙江省    |         0 |
|  5 | 河南省    |         0 |
|  6 | 广州市    |         1 |
|  7 | 深圳市    |         1 |
|  8 | 南京市    |         2 |
|  9 | 济南市    |         3 |
| 10 | 青岛市    |         3 |
| 11 | 杭州市    |         4 |
| 12 | 宁波市    |         4 |
| 13 | 郑州市    |         5 |
+----+-----------+-----------+
-- 查询城市所属省
SELECT a.id,a.area_name,p.area_name AS city 
FROM areas AS a LEFT JOIN (SELECT * FROM areas ) AS p ON a.id = p.parent_id;
+----+-----------+-----------+
| id | area_name | city      |
+----+-----------+-----------+
|  1 | 广东省    | 广州市    |
|  1 | 广东省    | 深圳市    |
|  2 | 江苏省    | 南京市    |
|  3 | 山东省    | 济南市    |
|  3 | 山东省    | 青岛市    |
|  4 | 浙江省    | 杭州市    |
|  4 | 浙江省    | 宁波市    |
|  5 | 河南省    | 郑州市    |
|  6 | 广州市    | NULL      |
|  7 | 深圳市    | NULL      |
|  8 | 南京市    | NULL      |
|  9 | 济南市    | NULL      |
| 10 | 青岛市    | NULL      |
| 11 | 杭州市    | NULL      |
| 12 | 宁波市    | NULL      |
| 13 | 郑州市    | NULL      |
+----+-----------+-----------+
-- 内连接
SELECT a.id,a.area_name,p.area_name AS city 
FROM areas AS a INNER JOIN (SELECT * FROM areas ) AS p ON a.id = p.parent_id;
+----+-----------+-----------+
| id | area_name | city      |
+----+-----------+-----------+
|  1 | 广东省    | 广州市    |
|  1 | 广东省    | 深圳市    |
|  2 | 江苏省    | 南京市    |
|  3 | 山东省    | 济南市    |
|  3 | 山东省    | 青岛市    |
|  4 | 浙江省    | 杭州市    |
|  4 | 浙江省    | 宁波市    |
|  5 | 河南省    | 郑州市    |
+----+-----------+-----------+

多表删除

-- 由于只有一张表,就用这一张演示,多表同理
-- 查看students
+----+--------+----------+------------+-------+
| id | name   | class_id | teacher_id | score |
+----+--------+----------+------------+-------+
|  1 | 张山   |        3 |          4 |    78 |
|  2 | 王五   |        1 |          1 |    85 |
|  3 | 赵六   |        4 |          2 |    66 |
|  4 | 陈七   |        3 |          4 |    90 |
|  5 | 阿狗   |        2 |          3 |    88 |
|  6 | 狗腿   |        2 |          3 |    95 |
|  7 | 陈七   |        3 |          4 |    90 |
|  8 | 小咪   |        4 |          2 |    98 |
|  9 | 富贵   |        1 |          1 |    83 |
| 10 | 王五   |        1 |          1 |    85 |
| 11 | 张伟   |       10 |         12 |   100 |
| 12 | 刘六   |       12 |         10 |   100 |
+----+--------+----------+------------+-------+
-- 会发现有几个重复的
-- 查看重复的用户
SELECT * FROM students GROUP BY name HAVING COUNT(name) > 1;
+----+--------+----------+------------+-------+
| id | name   | class_id | teacher_id | score |
+----+--------+----------+------------+-------+
|  2 | 王五   |        1 |          1 |    85 |
|  4 | 陈七   |        3 |          4 |    90 |
+----+--------+----------+------------+-------+
-- 接下来把存入时间晚的重复学生删除
DELETE t1 FROM students AS t1 
LEFT JOIN (SELECT * FROM students GROUP BY name HAVING COUNT(name)>1) AS t2 
ON t1.name = t2.name WHERE t1.id > t2.id;
+----+--------+----------+------------+-------+
| id | name   | class_id | teacher_id | score |
+----+--------+----------+------------+-------+
|  1 | 张山   |        3 |          4 |    78 |
|  2 | 王五   |        1 |          1 |    85 |
|  3 | 赵六   |        4 |          2 |    66 |
|  4 | 陈七   |        3 |          4 |    90 |
|  5 | 阿狗   |        2 |          3 |    88 |
|  6 | 狗腿   |        2 |          3 |    95 |
|  8 | 小咪   |        4 |          2 |    98 |
|  9 | 富贵   |        1 |          1 |    83 |
| 11 | 张伟   |       10 |         12 |   100 |
| 12 | 刘六   |       12 |         10 |   100 |
+----+--------+----------+------------+-------+
-- 🆗

为自己学习记录,错误之处请帮助指出,共同学习,谢谢

相关文章

  • MySQL-子查询及连接

    子查询 当一个查询是另一个查询的条件时,称之为子查询。 子查询必须用括号括起来。由比较运算符引发的子查询:先新建一...

  • MYSQL-子查询与连接

    子查询(subquery)指出现在其他SQL语句内的SELECT子句 子查询指嵌套在查询内部,且必须始终出现在圆括...

  • mysql 查询

    mysql的查询、子查询及连接查询 一、mysql查询的五种子句 where(条件查询)、having(筛选)、g...

  • SQL进阶2

    --表连接Join-- 查询所有学生的姓名、年龄及所在班级 使用子查询 使用from多表 使用多表连接 表 in...

  • MYSQL-子查询

    子查询是一个查询语句嵌套在另一个查询语句中。内层查询语句的结果,可以为外层查询语句提供查询条件。 子查询关键字:i...

  • mysql的查询、子查询及连接查询

    一、mysql查询的五种子句 where(条件查询)、having(筛选)、group by(分组)、order ...

  • mysql的查询、子查询及连接查询

    https://www.cnblogs.com/xiaoxi/p/6734025.html

  • Mysql--连接查询和子查询

    连接查询和子查询 一、连接查询 1.1 概念 连接查询:也可以叫跨表查询,需要关联多个表进行查询 1.2 根据年代...

  • 第三天下午、自连接、子连接、分页查询

    自连接 查询每个员工的编号、姓名、领导姓名 外连接查询 连接查询代码 课下作业题 子查询(分页查询) 查找工资最高...

  • MySQL-高级查询

    嵌套查询(子查询) 把内层的查询结果作为外层的查询条件 示例 多表查询 多个表之间联合查询 连接查询 内连接 外连...

网友评论

      本文标题:MySQL-子查询及连接

      本文链接:https://www.haomeiwen.com/subject/bwmdkctx.html