sql 各种 Join用法详解
在关系代数中,连接运算是由一个笛卡尔积运算和一个选取运算构成的。首先用笛卡尔积完成对两个数据集合的乘运算,然后对生成的结果集合进行选取运算,确保只把分别来自两个数据集合并且具有重叠部分的行合并在一起。连接的全部意义在于在水平方向上合并两个数据集合(通常是表),并产生一个新的结果集合,其方法是将一个数据源中的行于另一个数据源中和它匹配的行组合成一个新元组。SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。
不同的 SQL JOIN
连接类型 | 定义 |
Inner Join | 内连接是最常见的一种连接,它也被称为普通连接,只连接匹配的行(仅对满足连接条件的CROSS中的列)。它又分为等值连接(连接条件运算符为"=")和不等值连接(连接条件运算符不为"=",例如between...and)。 |
Full Outer Join | FULL JOIN 会从左表 和右表 那里返回所有的行。如果其中一个表的数据行在另一个表中没有匹配的行,那么对面的数据用NULL代替 |
Left Outer Join | LEFT JOIN返回左表的全部行和右表满足ON条件的行,如果左表的行在右表中没有匹配,那么这一行右表中对应数据用NULL代替。 |
Right Outer Join | RIGHT JOIN返回右表的全部行和左表满足ON条件的行,如果右表的行在左表中没有匹配,那么这一行左表中对应数据用NULL代替。 |
Cross Join | CROSS对两个表执行笛卡尔乘积。它为左表行和右表行的每种可能的组合返回一行。返回(左表行数*右表行数)行的表。 |
Appendix Natural Join |
自然连接是一种特殊的等值连接,在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。 |
Appendix 自连接 |
某个表和其自身连接,常用在同一表内不同数据间对同一列的比较 |
self join 常用在同一表内不同数据间对同一列的比较
select a.emp_no,a.emp_name,b.emp_no,b.emp_name,a.date_hired from
employee ajoin employee b
on (a.emp_no!=b.emp_no and a.date_hired=b.date_hired)
order by a.date_hired
这样会重复数据,只要加上一句 and a.emp_name>b.emp_name
UNION
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。
同时,每条 SELECT 语句中的列的顺序必须相同。
SQL UNION 语法
SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SQL UNION ALL 语法
UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值。
SELECT column_name(s) FROM table_name1 UNION ALL SELECT column_name(s) FROM table_name2另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
UNION 实例:
列出所有在中国和美国的不同的雇员名:
SELECT E_Name FROM Employees_ChinaUNION
SELECT E_Name FROM Employees_USA
UNION ALL实例:
列出在中国和美国的所有的雇员:
SELECT E_Name FROM Employees_ChinaUNION ALL
SELECT E_Name FROM Employees_USA
下面转自:http://blog.sina.com.cn/s/blog_7e5f32ff0102wbwc.html
性能优化
1.显示(explicit) inner join VS 隐式(implicit) inner join
如:
select * from table a inner join table b on a.id = b.id;
VS
select a.*, b.* from table a, table b where a.id = b.id;
我在数据库中比较(10w数据)得之,它们用时几乎相同,第一个是显示的inner join,后一个是隐式的inner join。
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 A inner join B on B.name = A.name left join C on C.name = B.name left join D on D.id = C.id where C.status>1 and D.status=1;
Great
select * from A inner join B on B.name = A.name left join C on C.name = B.name and C.status>1 left 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 t2 left 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 性能差别惊人:
由于客户数据量越来越大,在实践中让我发现mysql的exists与inner join 和 not exists与 left join 性能差别惊人。
我们一般在做数据插入时,想插入不重复的数据,或者盘点数据在一个表,另一个表否有存在相同的数据会用not exists和exists,例如:
- insert into t1(a1) select b1 from t2 where not exists(select 1 from t1 where t1.id = t2.r_id);
如果t1的数据量很大时,性能会非常慢。经过实践,用以下方法能提高很多。
- insert into t1(a1)
- select b1 from t2
- left join (select distinct t1.id from t1 ) t1 on t1.id = t2.r_id
- where t1.id is null;
- select * from t1 where exists(select 1 from t2 where t1.id=t2.r_id);
替换为:
- select t1.* from t1
- inner join (select distinct r_id from t2) t2 on t1.id= t2.r_id
这是实践的得出的结果。不知否有其他更好的方法,或则这个只是特例而已。
补充:MySQL STRAIGHT_JOIN 与 NATURAL JOIN的使用
长话短说:straight_join实现强制多表的载入顺序,从左到右,如:
...A straight_join B on A.name = B.name
straight_join完全等同于inner join 只不过,join语法是根据“哪个表的结果集小,就以哪个表为驱动表”来决定谁先载入的,而straight_join 会强制选择其左边的表先载入。
往往我们在分析mysql处理性能时,如(Explain),如果发现mysql在载入顺序不合理的情况下,可以使用这个语句,但往往mysql能够自动的分析并处理好。
更多内容参考:
MySQL STRAIGHT_JOIN 与 NATURAL JOIN
八.参考:
相关推荐
SQL中的left outer join,inner join,right outer join用法详解
SQL语句left join/right join/inner join 的用法比较 SQL语句left join/right join/inner join 的用法比较
详细说明JOIN的用法,包括LEFT JOIN、RIGHT JOIN、INNER JOIN、SELF JOIN、FULLJOIN
对于开发使用到数据库的应用,免不了就要使用联合查询,SQL中常用的联合查询有inner join、outer join和cross join;这三者的区别很多人都应该不是很清楚,包括我自己,下面我们一起来看看,如果你使用join连表,...
关于SQL 中的inner join的使用,是DOC文档,希望对大家有用,关于SQL 中的inner join的使用,是DOC文档,希望对大家有用
用途:帮助读者了解MySQL中的JOIN操作,掌握LEFT JOIN、ON条件过滤和笛卡尔积的使用方法,从而在实际开发中灵活运用JOIN操作实现表关联查询。本文还提供了扩展内容,如排名等应用场景,帮助读者进一步理解JOIN操作的...
关于 “A LEFT JOIN B ON 条件表达式” 的一点提醒 ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。 如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 ...
《精通SQ:结构化查询语言详解》全面讲解SQL语言,提供317个典型应用,读者可以随查随用,针对SQL Server和Oracle进行讲解,很有代表性。 全书共包括大小实例317个,突出了速学速查的特色。《精通SQ:结构化查询语言...
2.3.4 使用sql*plus执行sql语句 31 2.4 pl/sql简介 32 2.4.1 pl/sql的特点 32 2.4.2 pl/sql程序结构 33 第3章 创建、修改和删除表 37 3.1 表的基础知识 37 3.1.1 表的基本结构 37 3.1.2 表的种类 38 3.2 sql...
也是介于关系型数据库和非关系型数据库之间的数据存储产品,而众所周知SQL与NoSQL最大的不同之一就是不支持JOIN,在传统的数据库中,SQL JOIN子句允许你使用普通的字段,在两个或者是更多表中的组合表中的每行数据。...
2.3.2 获取SQL的各种详细信息 29 2.4 本章总结延伸与习题 32 2.4.1 总结延伸 32 2.4.2 习题训练 33 第3章 循规蹈矩——如何读懂SQL执行计划 34 3.1 执行计划分析概述 35 3.1.1 SQL执行计划是什么 35 3.1.2 ...
在laravel中我们常常会使用join,leftjion和rightjoin进行连表查询,非常的方便,但是我今天遇到一个问题,就是链表查询需要on多个条件,即我要订单的id和发货人都一样,默认的join只支持单个查询,所以我下面总结两...
2.3.2 获取SQL的各种详细信息 29 2.4 本章总结延伸与习题 32 2.4.1 总结延伸 32 2.4.2 习题训练 33 第3章 循规蹈矩——如何读懂SQL执行计划 34 3.1 执行计划分析概述 35 3.1.1 SQL执行计划是什么 35 3.1.2 ...
主要给大家介绍了关于Mysql巧用join优化sql的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Mysql具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
使用profile来分析慢sql mysql 的 sql 性能分析器主要用途是显示 sql 执行的整个过程中各项资源的使用情况。分析器可以更好的展示出不良 SQL 的性能问题所在。 最近遇到一个查询比较慢的sql语句,用了子查询,大概...
本章节我们将向大家介绍如何使用MySQL 的 JOIN 在两个或多个表中查询数据。 你可以在SELECT, UPDATE 和 DELETE 语句中使用Mysql 的 join 来联合多表查询。 以下我们将演示MySQL LEFT JOIN 和 JOIN 的使用的不同之处...
主要介绍了SQL JOIN 连接详细介绍及简单使用实例的相关资料,需要的朋友可以参考下
第 1 章 结构化查询语言 DM_SQL 简介 ....................................................................1 1.1 DM_SQL 语言的特点 ............................................................................
在上一篇文章中,我整理了pandas在数据合并和重塑中常用到的concat方法的使用说明。在这里,将接着介绍pandas中也常常用到的join 和merge方法 merge pandas的merge方法提供了一种类似于SQL的内存链接操作,官网文档...
RDD使用算子详解 Spark运行模式与作业提交 Spark 累加器与广播信号 基于Zookeeper搭建Spark高可用服务 火花 SQL: 日期帧和数据集 结构化API的基本使用 Spark SQL 外部数据源 Spark SQL常用聚合函数 Spark SQL JOIN...