mysql 子连接_MySQL-子查询及连接

子查询

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

子查询必须用括号括起来。

由比较运算符引发的子查询:

先新建一个数据表

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 |

+----+--------+---------------+--------------+-------+

-- 使用 ‘

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 |

+----+--------+----------+------------+-------+

-- 🆗

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值