MySQL中的连接查询使用方式

 更新时间:2025年11月20日 09:27:32   作者:Afison  
文章介绍了MySQL中的连接查询(JOIN),包括INNER JOIN、LEFT JOIN、RIGHT JOIN和FULL JOIN(通过UNION实现),通过示例和解释,文章说明了连接查询在数据规范化、提高查询效率和满足复杂查询需求方面的应用

MySQL使用连接查询(JOIN)是为了从多个相关表中获取数据。

连接查询是一种强大且常用的操作,可以根据某些条件将两张或多张表中的数据组合在一起,返回一个联合结果集。

1.为什么使用连接查询

数据规范化

  • 数据库设计时通常会将数据拆分到不同的表中,以减少数据冗余和提高数据一致性。这种方法称为规范化。
  • 例如,将用户信息存储在一个表中,将订单信息存储在另一个表中。这时,如果你需要获取某用户的订单信息,就需要使用连接查询将这两个表的数据组合在一起。

提高查询效率

  • 通过使用连接查询,可以减少重复的数据存储,优化数据的管理和查询效率。
  • 比如,一个表中存储用户ID,另一个表中存储用户详细信息,查询时只需要连接用户ID和详细信息表即可获取完整信息,而不需要在单个表中存储冗余数据。

复杂查询需求

  • 在实际应用中,很多查询需求都涉及多个表的数据。例如,报表生成、数据分析、统计等都需要从多个表中提取相关数据。
  • 连接查询可以实现这些复杂的查询需求,通过合并相关表的数据来满足业务逻辑。

2.主要类型的连接查询

INNER JOIN

  • 仅返回两个表中满足连接条件的记录。
SELECT users.username, orders.order_id
FROM users
INNER JOIN orders ON users.user_id = orders.user_id;
  • 说明:这将返回所有用户和他们的订单,前提是用户和订单在两个表中都有匹配。

LEFT JOIN (或 LEFT OUTER JOIN)

  • 返回左表中的所有记录,即使右表中没有匹配的记录。如果右表没有匹配,则结果为NULL。
SELECT users.username, orders.order_id
FROM users
LEFT JOIN orders ON users.user_id = orders.user_id;
  • 说明:这将返回所有用户以及他们的订单。如果某个用户没有订单,则相应的订单ID将为NULL。

RIGHT JOIN (或 RIGHT OUTER JOIN)

  • 返回右表中的所有记录,即使左表中没有匹配的记录。如果左表没有匹配,则结果为NULL。
SELECT users.username, orders.order_id
FROM users
RIGHT JOIN orders ON users.user_id = orders.user_id;
users. Username
  • 说明:这将返回所有订单以及对应的用户。如果某个订单没有匹配的用户,则相应的用户名将为NULL。

FULL JOIN (或 FULL OUTER JOIN)

  • 返回左表和右表中的所有记录,如果没有匹配则返回NULL。MySQL不直接支持FULL JOIN,可以通过UNION实现。
SELECT users.username, orders.order_id
FROM users
LEFT JOIN orders ON users.user_id = orders.user_id
UNION
SELECT users.username, orders.order_id
FROM users
RIGHT JOIN orders ON users.user_id = orders.user_id;
users. Username

3.测试连接查询

student 表

  • 存储学生的基本信息。
  • uid:学生的唯一标识(主键),自动递增。
  • name:学生姓名。
  • age:学生年龄。
  • sex:学生性别,使用枚举类型,值可以是'M'或'W'。

course 表

  • 存储课程的基本信息。
  • cid:课程的唯一标识(主键),自动递增。
  • cname:课程名称。
  • credit:课程学分。

exame 表

  • 存储考试信息,包括学生、课程和考试成绩。
  • uid:学生ID,对应student表中的uid
  • cid:课程ID,对应course表中的cid
  • time:考试时间。
  • score:考试成绩。
  • PRIMARY KEY(uid,cid):联合主键,确保每个学生在每门课程中只有一个成绩记录。
CREATE TABLE student(
uid INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age TINYINT UNSIGNED NOT NULL,
sex ENUM('M','W') NOT NULL);

CREATE TABLE course(
cid INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
cname VARCHAR(50) NOT NULL,
credit TINYINT UNSIGNED NOT NULL);

CREATE TABLE exame(
uid INT UNSIGNED NOT NULL,
cid INT UNSIGNED NOT NULL,
time DATE NOT NULL,
score FLOAT NOT NULL,
PRIMARY KEY(uid,cid));

插入一些数据

-- 插入数据到 student 表
INSERT INTO student (name, age, sex) VALUES 
('Alice', 20, 'W'),
('Bob', 21, 'M'),
('Charlie', 22, 'M'),
('David', 20, 'M'),
('Eve', 21, 'W');

-- 插入数据到 course 表
INSERT INTO course (cname, credit) VALUES 
('Mathematics', 3),
('Physics', 4),
('Chemistry', 3),
('Biology', 2),
('Computer Science', 3);

-- 插入数据到 exame 表
INSERT INTO exame (uid, cid, time, score) VALUES 
(1, 1, '2024-01-10', 85.5),
(1, 2, '2024-01-11', 90.0),
(2, 1, '2024-01-9', 88.0),
(2, 3, '2024-01-10', 92.5),
(3, 4, '2024-01-12', 75.0),
(3, 5, '2024-01-9', 80.0),
(4, 2, '2024-01-12', 85.0),
(4, 3, '2024-01-12', 87.5),
(5, 1, '2024-01-11', 89.0),
(5, 5, '2024-01-11', 95.0);

 

 

 

内连接

SELECT a.属性名1,a.属性名2,...,b,属性名1,b.属性名2... FROM table_name1 a inner join table_name2 b on a.id = b.id where a.属性名 满足某些条件;

预置条件:uid:1 cid:2
select score from exame where uid=1 and cid=2;
select a.uid,a.name,a.age,a.sex from student a where a.uid=1;
select c.score from exame c where c.uid=1 and c.cid=2;

连接两张表查询

// on a.uid=c.uid 区分大表 和 小表,按照数据量来区分,小表永远是整表扫描,然后去大表搜索 // 从student小表中取出所有的a.uid,然后拿着这些uid去exame大表中搜索 // 对于inner join内连接,过滤条件写在where的后面和on连接条件里面,效果是一样的

select a.uid,a.name,a.age,a.sex,c.score from student a
inner join exame c on a.uid=c.uid where c.uid=1 and c.cid=2;

select b.cid,b.cname,b.credit from course b where b.cid=2;

 

select a.uid,a.name,a.age,a.sex,b.cid,b.cname,b.credit,c.score
from exame c
inner join student a on c.uid=a.uid
inner join course b on c.cid=b.cid
where c.uid=1 and c.cid=2;

select a.uid,a.name,a.age,a.sex,b.cid,b.cname,b.credit,c.score
from exame c
inner join student a on c.uid=a.uid
inner join course b on c.cid=b.cid
where c.cid=2 and c.score>=90.0;

select b.cid,b.cname,b.credit,count(*)
from exame c
inner join course b on c.cid=b.cid
where c.score>=90.0
group by c.cid
having c.cid=2;//分组以后的过滤

select b.cid,b.cname,b.credit,count(*) cnt
from exame c
inner join course b on c.cid=b.cid
where c.score>=90.0
group by c.cid
order by cnt;

外连接查询

左连接查询

SELECT a.属性名列表, b.属性名列表 FROM table_name1 a LEFT [OUTER] JOIN table_name2 b on a.id = b.id;

// 把left这边的表所有的数据显示出来,在右表中不存在相应数据,则显示NULL
select a.* from User a left outer join Orderlist b on a.uid=b.uid where
a.orderid is null;

 例子:

select a.*,b.* from student a left join exame b on a.uid=b.uid;

找出没有考过试的

select a.*,b.* from student a left join exame b on a.uid=b.uid where b.cid is null;

内连接结果如下

左连接结果如下

问题,为啥左连接没有把左表全部信息显示,左连接和内连接结果一样

若把where条件放到连接条件on后面

原因分析:

先用b.cid把b表过滤下

 这个内连接和外连接毫无区别,是一样的。所以外连接要把过滤条件写到on中

外连接查不存在的场景,还带有一定的限制条件,限制条件加到on的连接条件后面,where的过滤条件后面写null判空。

右连接查询

SELECT a.属性名列表, b.属性名列表 FROM table_name1 a LEFT [OUTER] JOIN table_name2 b on a.id = b.id;

// 把right这边的表所有的数据显示出来,在左表中不存在相应数据,则显示NULL
select a.* from User a right outer join Orderlist b on a.uid=b.uid where
b.orderid is null;
select * from student where uid not in (select distinct uid from exame);

select distinct uid from exame-》会产生一张中间表存储结果供外面的sql来查询

not in 对于索引的命中并不高

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MySQL级联复制下如何进行大表的字段扩容

    MySQL级联复制下如何进行大表的字段扩容

    这篇文章主要介绍了MySQL级联复制下进行大表的字段扩容,库表信息环境是Mysql 8.0.22,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • MySQL分区分表实现方法示例详解

    MySQL分区分表实现方法示例详解

    ShardingSphere-JDBC通过在应用层进行数据分片,可以帮你轻松实现分区、分表和分库,下面我用具体的配置和代码示例来说明如何使用,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-10-10
  • MySQL主从复制原理以及需要注意的地方

    MySQL主从复制原理以及需要注意的地方

    这篇文章主要介绍了MySQL主从复制原理以及需要注意的地方,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-11-11
  • mysql如何利用Navicat导出和导入数据库的方法

    mysql如何利用Navicat导出和导入数据库的方法

    这篇文章主要介绍了mysql如何利用Navicat导出和导入数据库的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • mysql中的find_in_set字符串查找函数解析

    mysql中的find_in_set字符串查找函数解析

    这篇文章主要介绍了mysql中的find_in_set字符串查找函数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Mysql 索引从入门到精通(从原理到实践)

    Mysql 索引从入门到精通(从原理到实践)

    本文介绍MySQL索引深度解析:从原理到实践,本文涵盖索引基础概念、类型、底层原理及管理策略,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-10-10
  • MySQL中explain语句的基本使用教程

    MySQL中explain语句的基本使用教程

    这篇文章主要给大家介绍了关于MySQL中explain语句的基本使用教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 在Centos7环境安装MySQL超详细教程

    在Centos7环境安装MySQL超详细教程

    MySQL是一种开源的关系型数据库管理系统(RDBMS),它是目前最流行和广泛使用的数据库之一,这篇文章主要给大家介绍了关于在Centos7环境安装MySQL的相关资料,需要的朋友可以参考下
    2023-11-11
  • 通过sql语句将blob里的char取出来转成数字保存在其它字段

    通过sql语句将blob里的char取出来转成数字保存在其它字段

    现在需要将blob里地17、18、19三个字段里的数据作为数字保存在blob外新增的三个字段Gem1 Gem2 Gem3上。
    2011-09-09
  • MySQL mysqladmin客户端的使用简介

    MySQL mysqladmin客户端的使用简介

    这篇文章主要介绍了MySQL mysqladmin客户端的使用简介,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-03-03

最新评论