mysql的join查询分类

博客介绍了SQL语句分类,重点讲解join语句分类,包括内连接、左连接等。给出建表及各类join查询的SQL实例,还阐述了join查询的优化场景,如优化子查询、解决update操作from表问题、优化聚合子查询等,展示了join在查询速度上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.语句分类

2.join语句分类

      join的查询速度快于子查询,主要是因为子查询过程中需要创建中间表  

     内连接:inner join on = join on

     左外连接:left join on = LEFT OUTER JOIN on

     右外连接:right join on = right OUTER JOIN on

     全外连接: full join on 但mysql不支持,可使用union 连接左外连接和右外连接数据

     交叉连接:CROSS JOIN 相当于a*b表的结果,没有on从句

 

3.sql实例

a.建表

/* 老师表   */
CREATE TABLE teachers (
  id int(4) not null auto_increment,
  name varchar(20) not null default '' comment '老师名称',
  subject varchar(20) not null default '' comment '学科',
    primary key(id)
)engine=INNODB auto_increment=1 DEFAULT charset=utf8 comment '老师表';

insert into teachers (name,subject) values ('张三','数学'),('李四','语文'),('王五','英语'),('张柳','历史'),('三七','地理');

/* 父亲表   */
DROP table father;
create table father(
  id int(4) not null auto_increment,
  name varchar(20) not null default '' comment '名称',
  children varchar(20) not null default '' comment '孩子的名称',
  primary key (id)
)engine=innodb auto_increment=1 default charset=utf8 comment '父亲表';

insert into father(name,children) values ('张三','小孩1'),('李四','小孩2'),('王五','小孩3'),('大大','小孩4'),('小杰','小孩5');

create table teacherDate(
 id int(4) not null auto_increment,
 name varchar(20) not null default '' comment '老师名称',
 date date not null comment '上课日期',
 hour int(4) not null default 0 comment '当天的上课时间',
 primary key(id)
)engine=innodb auto_increment=1 default charset=utf8 comment '老师的上课时间表';

insert into teacherDate (name,date,hour) values ('张三','2019-06-11',3),('张三','2019-06-10',4),('张三','2019-06-09',5),('张三','2019-06-08',6)
,('李四','2019-06-11',3),('李四','2019-06-10',4),('李四','2019-06-09',5),('李四','2019-06-08',6)
,('王五','2019-06-11',3),('王五','2019-06-10',4),('王五','2019-06-09',5),('张柳','2019-06-08',6)
,('三七','2019-06-10',4),('三七','2019-06-09',5),('张柳','2019-06-11',6);

b.内连接

----属于老师且是父亲的信息 :两表求并集  inner join = join----
SELECT a.name,a.subject,b.children from teachers a JOIN father b on a.name=b.name;
SELECT a.name,a.subject,b.children from teachers a INNER JOIN father b on a.name=b.name;

c.左连接

----是老师但不是父亲的 left join = LEFT OUTER JOIN ----
SELECT a.name,a.subject,b.children from teachers a left join father b on a.name=b.name where b.name is null ;
SELECT a.name,a.subject,b.children from teachers a left outer join father b on a.name=b.name where b.name is null ;

d.右连接

----是父亲但不是老师 right join = right OUTER JOIN  ----
select b.name,a.subject,b.children from teachers a right join father b on a.name=b.name where a.name is null;

e.全外连接

----选出老师以及父亲的全部信息 ----
SELECT a.name ,a.subject,b.children from teachers a FULL JOIN father b on a.name=b.name ;    /* mysql不支持full join on */

/* 将左关联和右关联查询结果使用union合并起来 */
SELECT a.name,a.subject,b.children from teachers a left join father b on a.name=b.name
   union
   select b.name,a.subject,b.children from teachers a right join father b on a.name=b.name;

f.交叉连接

---- 交叉连接:相当于A表*B表  没有on从句 ----
SELECT a.name,a.subject,b.children from teachers a CROSS JOIN father b ;

 

4.join查询的优化场景

a.优化子查询

子查询: SELECT COUNT(a.id) from shops a where a.sid in (SELECT b.sid from consignee b where b.static=1);

 join优化:SELECT COUNT(a.id) from shops a LEFT JOIN consignee b ON a.sid=b.sid where b.static=1;

join优化后的查询相当于子查询时间的一半

b.update不能操作from中的表

需求:更新 同时是老师和父亲的人员的学科信息为 家庭学

update teachers set subject='家庭学' where name in(/* 不能更新from从句中的表 */
  SELECT a.name from teachers a inner join father b on a.name=b.name
);    //[Err] 1093 - You can't specify target table 'teachers' for update in FROM clause

可使用如下语句:

UPDATE teachers d join (SELECT a.name from teachers a inner join father b on a.name=b.name) c on d.name=c.name set d.subject='家庭学';

update teachers a inner join father b on a.name=b.name set a.subject='家庭学3';

UPDATE teachers a , father b set a.subject='家庭学2' where a.name=b.name ;

c.join优化聚合子查询

查询出各个老师上课最多的日期

--查询特定老师上课最多的日期--

select c.id,c.name,max(c.hour) from teacherDate c where c.name='三七' ;

--查询老师的上课信息--
SELECT a.name,a.`subject`,b.date,b.hour from teachers a join teacherDate b on a.name=b.name;

通过将1的查询结果作为2的子查询的方式进行处理
SELECT a.name,a.`subject`,b.date,b.hour from teachers a join teacherDate b on a.name=b.name
  where b.hour in (select max(c.hour) from teacherDate c where c.name=b.name );

d.选出每个人打怪做多的两天的记录

MySQL 中,`LEFT JOIN` 是一种非常常用的多表查询方式,它用于从两个或多个表中检索数据,并以左表(第一个表)为基础,返回左表中的所有记录,即使右表中没有匹配的行,也会返回 `NULL` 值。`LEFT JOIN` 也被称为 `LEFT OUTER JOIN`。 ### 基本语法 ```sql SELECT 列名 FROM 左表 LEFT JOIN 右表 ON 左表.列名 = 右表.列名; ``` 在多表查询中,可以连续使用多个 `LEFT JOIN` 来连接多个表。例如: ```sql SELECT 列名 FROM 表1 LEFT JOIN 表2 ON 表1.列名 = 表2.列名 LEFT JOIN 表3 ON 表1.列名 = 表3.列名 LEFT JOIN 表4 ON 表1.列名 = 表4.列名; ``` ### 使用示例 以下是一个使用 `LEFT JOIN` 查询多个表的示例: 假设有以下三张表: 1. `runoob_tbl`(文章表): | huthon_id | huthon_title | huthon_author | |-----------|---------------------|---------------| | 1 | MySQL 入门教程 | 张三 | | 2 | Python 编程基础 | 李四 | | 3 | Java 核心编程 | 王五 | 2. `tcount_tbl`(文章计数表): | runoob_author | huthon_count | |----------------|---------------| | 张三 | 10 | | 李四 | 5 | 3. `category_tbl`(文章分类表): | category_id | category_name | |-------------|----------------| | 1 | 数据库 | | 2 | 编程语言 | #### 查询目标: 查询每位作者的文章信息,包括作者名、文章标题、文章数量以及所属分类。 ```sql SELECT a.huthon_author AS author, a.huthon_title AS title, b.huthon_count AS count, c.category_name AS category FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.huthon_author = b.runoob_author LEFT JOIN category_tbl c ON a.huthon_id = c.category_id; ``` #### 查询结果: | author | title | count | category | |--------|-------------------|-------|-----------| | 张三 | MySQL 入门教程 | 10 | 数据库 | | 李四 | Python 编程基础 | 5 | 编程语言 | | 王五 | Java 核心编程 | NULL | NULL | 在这个查询中: - `LEFT JOIN tcount_tbl b ON a.huthon_author = b.runoob_author` 确保了即使某个作者在 `tcount_tbl` 中没有对应的计数记录,也会显示文章信息,只是 `huthon_count` 为 `NULL`。 - `LEFT JOIN category_tbl c ON a.huthon_id = c.category_id` 确保了即使某篇文章没有分类信息,也会保留文章信息,只是 `category_name` 为 `NULL`。 ### 注意事项: - `LEFT JOIN` 会返回左表中的所有记录,即使右表中没有匹配的行。 - 如果右表中没有匹配的行,则相关字段的值为 `NULL`。 - 在多表连接中,`LEFT JOIN` 的顺序可能会影响查询结果,因此需要根据业务逻辑选择合适的连接顺序。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值