文章转载的:http://www.cnblogs.com/BeginMan/p/3754322.html

一.多表查询方法分类

1.交叉连接查询(得到的是两个表的乘积,类似于矩阵乘积)

select * from A, B;

2.内连接查询(关键字inner join -- inner可以省略)

隐式内连接 : select * from A,B  where 条件;   //where 关键字

显式内连接:select * from Ainner join Bon 条件; //on 关键字

3.外连接查询(outer join --outer可以省略)

左外连接:left outer join

select * from  A left outer join Bon 条件;

右外连接:right outer join

select * from A right outer join B on 条件;

二.Join语法概述

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

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

table1:左表;table2:右表。 在 INNER|LEFT|RIGHT JOIN 关键字左侧的为左表,在右侧的为右表。

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)产生一套完整的记录(左表Table 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)

求差集:

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

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

SELECT * FROM A LEFT JOIN B ON A.name = B.name

WHERE B.id IS NULL

union

SELECT * FROM A right JOIN B ON A.name = B.name

WHERE 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。

七.性能优化

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 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中调用多个表_MySQL 多表查询相关推荐

  1. mysql中如何删除空记录表_mysql删除表中的记录

    大家都知道,在MySQL中删除一个表中的记录有两种方法,一种是DELETE FROM TABLENAME WHERE... , 还有一种是TRUNCATE TABLE TABLENAME. DELET ...

  2. c efcore.mysql_EF Core在mysql中调用存储过程

    EF Core在mysql中调用存储过程,博主找了很多,然而大多都是EF Core+SqlServer的或者EF Core+Oracle的,并没有正对Mysql的Pomelo驱动的,所以查找了一些资料 ...

  3. mysql中存储引擎是啥_mysql中的存储引擎

    mysql存储引擎概述 什么是存储引擎? MySQL中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力. ...

  4. mysql分析表_MySQL分析表有什么用

    MySQL中使用ANALYZE TABLE语句来分析表,该语句的基本语法如下: ANALYZE TABLE 表名1 [,表名2-] ; 使用ANALYZE TABLE分析表的过程中,数据库系统会对表加 ...

  5. mysql中递增列_如何使用JDBC在MySQL中创建带有自动递增列的表?

    在创建表时,在某些情况下,我们需要自动生成/增加列的值(例如ID).各种数据库以不同的方式支持此功能. 在MySQL数据库中,您可以使用以下语法声明列自动递增.CREATE TABLE table_n ...

  6. mysql中的删除语法错误_mysql – EXPLAIN中的SQL语法错误

    我试图让一个解释命令在 mysql中工作.我正在尝试解决此删除查询的性能问题: DELETE FROM boost_cache_relationships WHERE base_dir = 'cach ...

  7. python数据库建表_mysql数据表如何创建

    在 MySQL 中,可以使用 CREATE TABLE 语句创建表.其语法格式为:CREATE TABLE <表名> ([表定义选项])[表选项][分区选项]; 其中,[表定义选项]的格式 ...

  8. Mysql中按某一字段去重,并查询去重后的所有字段

    1.Mysql中按某一字段去重,并查询去重后的所有字段 SELECT pnum, name   FROM products AA  WHERE id =        (SELECT MIN(id)  ...

  9. mysql中更新的命令是_MySQL 语言中,更新表数据的命令是( )。_学小易找答案

    [简答题]MySQL 语言中包含数都定义语言.数据操纵语言和数据控制语言,分别有哪些功能? [单选题]查询员工工资信息时,结果按工资降序排列,正确的是( ). [简答题]arrayList测验 [填空 ...

最新文章

  1. 给老婆写个Python教程
  2. ASP.NET Razor – C# 逻辑条件简介
  3. 调研字节码插桩技术,用于系统监控设计和实现
  4. python如何进行数据抓取_如何进行手机APP的数据爬取?
  5. VMware大会宋家瑜言虚拟化2015年方至巅峰
  6. 中大计算机研究生英语免修条件,通知|关于接受2017级理科研究生 基础英语课程免修免考申请的通知...
  7. bean的属性类型----ibatis类型-------oracle数据库类型
  8. 通过配置文件登陆有密码的mysql不需要输入密码
  9. oracle 中累加函数,Oracle 分析函数分组累加!
  10. dos命令安装windows服务
  11. Regionals 2014 Asia - Dhaka H 暴力
  12. git 本地与远程仓库出现代码冲突解决方法
  13. 模拟个密保卡的效果,没用JS框架
  14. day04 JavaScript高级程序设计 阅读总结
  15. 你应该会的一道多线程笔试题
  16. python编程基础-task5-面向对象的编程
  17. 53.大数据之旅——java分布式项目14-信息检索技术之Lucene,Solr
  18. 同花顺校园招聘笔试题 2014 武汉站
  19. linux ida和idr分配机制
  20. 国家自然科学基金 计算机视觉,【科研新成果】我院2019年国家自然科学基金项目取得新突破...

热门文章

  1. git添加/删除远程仓库
  2. zoj 2975 Kinds of Fuwas(数学题)
  3. Linux桌面系统x11原理简介
  4. 美团/饿了么外卖CPS联盟返利公众号小程序核心源码
  5. python ERROR: Could not find a version that satisfies the requirement requests (from versions: none)
  6. python回溯法解9*9数独
  7. 【移动端二】夜神模拟器
  8. php swoole 教程,Swoole基础入门
  9. 《ChatGPT》自动写代码、写作文,使用教程来了
  10. 【Ubuntu】虚拟摄像头,并应用在Teams上