0

0

Mysql Join语法解析与性能分析

php中文网

php中文网

发布时间:2016-06-01 13:13:00

|

1373人浏览过

|

来源于php中文网

原创

一.Join语法概述

join 用于多表中字段之间的联系,语法如下:

... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona

table1:左表;table2:右表。

JOIN 按照功能大致分为如下三类:

INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录。

LEFT JOIN(左连接):取得左表(table1)完全记录,即是右表(table2)并无对应匹配记录。

RIGHT JOIN(右连接):与 LEFT JOIN 相反,取得右表(table2)完全记录,即是左表(table1)并无匹配对应记录。

注意:mysql不支持Full join,不过可以通过UNION 关键字来合并 LEFT JOIN 与 RIGHT JOIN来模拟FULL join.

接下来给出一个列子用于解释下面几种分类。如下两个表(A,B)

mysql> select A.id,A.name,B.name from A,B where A.id=B.id;+----+-----------+-------------+| id | name | name |+----+-----------+-------------+|1 | Pirate | Rutabaga||2 | Monkey| Pirate||3 | Ninja | Darth Vader ||4 | Spaghetti| Ninja |+----+-----------+-------------+4 rows in set (0.00 sec)

二.Inner join

内连接,也叫等值连接,inner join产生同时符合A和B的一组数据。

mysql> select * from A inner join B on A.name = B.name;+----+--------+----+--------+| id | name | id | name |+----+--------+----+--------+|1 | Pirate |2 | Pirate ||3 | Ninja|4 | Ninja|+----+--------+----+--------+

三.Left join

mysql> select * from A left join B on A.name = B.name;#或者:select * from A left outer join B on A.name = B.name;+----+-----------+------+--------+| id | name| id | name |+----+-----------+------+--------+|1 | Pirate|2 | Pirate ||2 | Monkey| NULL | NULL ||3 | Ninja |4 | Ninja||4 | Spaghetti | NULL | NULL |+----+-----------+------+--------+4 rows in set (0.00 sec)

left join,(或left outer join:在Mysql中两者等价,推荐使用left join.)左连接从左表(A)产生一套完整的记录,与匹配的记录(右表(B)) .如果没有匹配,右侧将包含null。

如果想只从左表(A)中产生一套记录,但不包含右表(B)的记录,可以通过设置where语句来执行,如下:

mysql> select * from A left join B on A.name=B.name where A.id is null or B.id is null;+----+-----------+------+------+| id | name| id | name |+----+-----------+------+------+|2 | Monkey| NULL | NULL ||4 | Spaghetti | NULL | NULL |+----+-----------+------+------+2 rows in set (0.00 sec)

同理,还可以模拟inner join. 如下:

mysql> select * from A left join B on A.name=B.name where A.id is not null and B.id is not null;+----+--------+------+--------+| id | name | id | name |+----+--------+------+--------+|1 | Pirate |2 | Pirate ||3 | Ninja|4 | Ninja|+----+--------+------+--------+2 rows in set (0.00 sec)

求差集:

根据上面的例子可以求差集,如下:

SELECT * FROM A LEFT JOIN B ON A.name = B.nameWHERE B.id IS NULLunionSELECT * FROM A right JOIN B ON A.name = B.nameWHERE A.id IS NULL;# 结果	+------+-----------+------+-------------+| id | name	| id | name		|+------+-----------+------+-------------+|	2 | Monkey	| NULL | NULL		||	4 | Spaghetti | NULL | NULL		|| NULL | NULL	|	1 | Rutabaga	|| NULL | NULL	|	3 | Darth Vader |+------+-----------+------+-------------+

四.Right join

mysql> select * from A right join B on A.name = B.name;+------+--------+----+-------------+| id | name | id | name|+------+--------+----+-------------+| NULL | NULL |1 | Rutabaga||1 | Pirate |2 | Pirate|| NULL | NULL |3 | Darth Vader ||3 | Ninja|4 | Ninja |+------+--------+----+-------------+4 rows in set (0.00 sec)

同left join。

五.Cross join

cross join:交叉连接,得到的结果是两个表的乘积,即笛卡尔积

笛卡尔(Descartes)乘积又叫直积。假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以扩展到多个集合的情况。类似的例子有,如果A表示某学校学生的集合,B表示该学校所有课程的集合,则A与B的笛卡尔积表示所有可能的选课情况。

mysql> select * from A cross join B;+----+-----------+----+-------------+| id | name| id | name|+----+-----------+----+-------------+|1 | Pirate|1 | Rutabaga||2 | Monkey|1 | Rutabaga||3 | Ninja |1 | Rutabaga||4 | Spaghetti |1 | Rutabaga||1 | Pirate|2 | Pirate||2 | Monkey|2 | Pirate||3 | Ninja |2 | Pirate||4 | Spaghetti |2 | Pirate||1 | Pirate|3 | Darth Vader ||2 | Monkey|3 | Darth Vader ||3 | Ninja |3 | Darth Vader ||4 | Spaghetti |3 | Darth Vader ||1 | Pirate|4 | Ninja ||2 | Monkey|4 | Ninja ||3 | Ninja |4 | Ninja ||4 | Spaghetti |4 | Ninja |+----+-----------+----+-------------+16 rows in set (0.00 sec)#再执行:mysql> select * from A inner join B; 试一试#在执行mysql> select * from A cross join B on A.name = B.name; 试一试

实际上,在 MySQL 中(仅限于 MySQL) CROSS JOIN 与 INNER JOIN 的表现是一样的,在不指定 ON 条件得到的结果都是笛卡尔积,反之取得两个表完全匹配的结果。 INNER JOIN 与 CROSS JOIN 可以省略 INNER 或 CROSS 关键字,因此下面的 SQL 效果是一样的:

... FROM table1 INNER JOIN table2... FROM table1 CROSS JOIN table2... FROM table1 JOIN table2

六.Full join

mysql> select * from A left join B on B.name = A.name 	-> union 	-> select * from A right join B on B.name = A.name;+------+-----------+------+-------------+| id | name	| id | name		|+------+-----------+------+-------------+|	1 | Pirate	|	2 | Pirate	||	2 | Monkey	| NULL | NULL		||	3 | Ninja	 |	4 | Ninja	 ||	4 | Spaghetti | NULL | NULL		|| NULL | NULL	|	1 | Rutabaga	|| NULL | NULL	|	3 | Darth Vader |+------+-----------+------+-------------+6 rows in set (0.00 sec)

全连接产生的所有记录(双方匹配记录)在表A和表B。如果没有匹配,则对面将包含null。

eSiteGroup站群管理系统1.0.4
eSiteGroup站群管理系统1.0.4

eSiteGroup站群管理系统是基于eFramework低代码开发平台构建,是一款高度灵活、可扩展的智能化站群管理解决方案,全面支持SQL Server、SQLite、MySQL、Oracle等主流数据库,适配企业级高并发、轻量级本地化、云端分布式等多种部署场景。通过可视化建模与模块化设计,系统可实现多站点的快速搭建、跨平台协同管理及数据智能分析,满足政府、企业、教育机构等组织对多站点统一管控的

下载

七.性能优化

1.显示(explicit) inner join VS 隐式(implicit) inner join

如:

select * fromtable a inner join table bon a.id = b.id;

VS

select a.*, b.*from table a, table bwhere a.id = b.id;

我在数据库中比较(10w数据)得之,它们用时几乎相同,第一个是显示的inner join,后一个是隐式的inner join。

参照:Explicit vs implicit SQL joins

2.left join/right join VS inner join

尽量用inner join.避免 LEFT JOIN 和 NULL.

在使用left join(或right join)时,应该清楚的知道以下几点:

(1). on与 where的执行顺序

ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据,在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后,WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。

所以我们要注意:在使用Left (right) join的时候,一定要在先给出尽可能多的匹配满足条件,减少Where的执行。如:

PASS

select * from Ainner join B on B.name = A.nameleft join C on C.name = B.nameleft join D on D.id = C.idwhere C.status>1 and D.status=1;

Great

select * from Ainner join B on B.name = A.nameleft join C on C.name = B.name and C.status>1left join D on D.id = C.id and D.status=1

从上面例子可以看出,尽可能满足ON的条件,而少用Where的条件。从执行性能来看第二个显然更加省时。

(2).注意ON 子句和 WHERE 子句的不同

如作者举了一个列子:

mysql> SELECT * FROM product LEFT JOIN product_details	ON (product.id = product_details.id)	AND product_details.id=2;+----+--------+------+--------+-------+| id | amount | id | weight | exist |+----+--------+------+--------+-------+|1 |100 | NULL | NULL |NULL ||2 |200 |2 | 22 | 0 ||3 |300 | NULL | NULL |NULL ||4 |400 | NULL | NULL |NULL |+----+--------+------+--------+-------+4 rows in set (0.00 sec)mysql> SELECT * FROM product LEFT JOIN product_details	ON (product.id = product_details.id)	WHERE product_details.id=2;+----+--------+----+--------+-------+| id | amount | id | weight | exist |+----+--------+----+--------+-------+|2 |200 |2 | 22 | 0 |+----+--------+----+--------+-------+1 row in set (0.01 sec)

从上可知,第一条查询使用 ON 条件决定了从 LEFT JOIN的 product_details表中检索符合的所有数据行。第二条查询做了简单的LEFT JOIN,然后使用 WHERE 子句从 LEFT JOIN的数据中过滤掉不符合条件的数据行。

(3).尽量避免子查询,而用join

往往性能这玩意儿,更多时候体现在数据量比较大的时候,此时,我们应该避免复杂的子查询。如下:

PASS

insert into t1(a1) select b1 from t2 where not exists(select 1 from t1 where t1.id = t2.r_id); 

Great

insert into t1(a1)select b1 from t2left join (select distinct t1.id from t1 ) t1 on t1.id = t2.r_id where t1.id is null;

这个可以参考mysql的exists与inner join 和 not exists与 left join 性能差别惊人

八.参考:

A Visual Explanation of SQL Joins

五种提高 SQL 性能的方法

关于 MySQL LEFT JOIN 你可能需要了解的三点

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

286

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

126

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

42

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

19

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

23

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

14

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

421

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

51

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号