1、基本连接

不同类型的数据,存储在多个表中,而所谓多表连接,就是将多个表联合返回一组输出。

1.1 等值连接

基本的连接方式非常简单,只需要在WHERE子句中规定如何关联即可,如下:
SELECT
vend_name,
prod_name,
prod_price
FROM
vendors,
products
WHERE
vendors.vend_id = products.vend_id
ORDER BY
vend_name, prod_name;
11
 
1
SELECT 
2
  vend_name,
3
  prod_name,
4
  prod_price
5
FROM
6
  vendors, 
7
  products
8
WHERE
9
  vendors.vend_id = products.vend_id
10
ORDER BY
11
  vend_name, prod_name;

最终的输出结果中,会包含另一张表products中的prod_name和prod_price两个列。

在以上的示例中,我们指定了WHERE子句中 vendors.vend_id = products.vend_id ,所以在连接两个表时,你实际上做的是将第一个表中的每一行与第二个表中的每一行配对,WHERE子句作为过滤条件。

这种方式,也叫做等值连接,也称为内部连接(INNER JOIN)。当两个关系不存在公共属性(即字段名称和类型完全相同)时,以取值具有可比性的同类型属性为基础进行连接。

实际上,你也可以用稍微不同的格式来进行,以下和之前示例的效果是一样的:
SELECT
vend_name,
prod_name,
prod_price
FROM
vendors INNER JOIN products ON vendors.vend_id = prodcuts.vend_id;
6
 
1
SELECT
2
  vend_name,
3
  prod_name,
4
  prod_price
5
FROM
6
  vendors INNER JOIN products ON vendors.vend_id = prodcuts.vend_id;

多表连接中对于表连接的数量是没有限制的,规则也都相同,如连接三个表,以上两种方式分别为:
SELECT
vend_name,
prod_name,
prod_price,
quantity
FROM
vendors,
products,
orderitems
WHERE
vendors.vend_id = products.vend_id
AND
orderitems.prod_id = products.prod_id
ORDER BY
vend_name, prod_name;
15
 
1
SELECT
2
  vend_name,
3
  prod_name,
4
  prod_price,
5
  quantity
6
FROM
7
  vendors, 
8
  products,
9
  orderitems
10
WHERE
11
  vendors.vend_id = products.vend_id
12
  AND
13
  orderitems.prod_id = products.prod_id
14
ORDER BY
15
  vend_name, prod_name;

SELECT
vend_name,
prod_name,
prod_price,
quantity
FROM
(vendors INNER JOIN products ON vendors.vend_id = prodcuts.vend_id)
INNER JOIN orderitems ON orderitems.prod_id = products.prod_id;
9
 
1
SELECT
2
  vend_name,
3
  prod_name,
4
  prod_price,
5
  quantity
6
FROM
7
  (vendors INNER JOIN products ON vendors.vend_id = prodcuts.vend_id)
8
    INNER JOIN orderitems ON orderitems.prod_id = products.prod_id;
9
  

1.2 笛卡儿积

由没有连接条件的表关系返回的结果为笛卡儿积。检索出来的行的数目将是第一个表中的行数乘以第二个表中的行数。
SELECT
vend_name,
prod_name,
prod_price
FROM
vendors,
products
ORDER BY
vend_name, prod_name;
9
 
1
SELECT
2
  vend_name,
3
  prod_name,
4
  prod_price
5
FROM
6
  vendors,
7
  products
8
ORDER BY
9
  vend_name, prod_name;

简单地说,第一个表中的每一行会和第二个表中的每一行一一匹配为新的行筛出。

这种表往往并不是我们所需要的,因为表间关系混乱,每条数据进行了无差别匹配,包括了它从业务逻辑上根本就不应该对应的东西。

所以,在进行表连接时一定要保证WHERE子句。



2、高级联结

2.1 自连接

自连接即两个相同的表的连接,往往作为外部语句用来替代从相同表中检索数据时使用的子查询语句。

如下例为,加入你发现某物品(ID为DTNTR)存在问题,因此想知道该产品供应商的其他产品是否也存在同样的问题:
SELECT
prod_id,
prod_name
FROM
products
WHERE
vend_id =
(SELECT vend_id FROM products WHERE prod_id = 'DTNTR');
8
 
1
SELECT
2
  prod_id,
3
  prod_name
4
FROM
5
  products
6
WHERE
7
  vend_id = 
8
  (SELECT vend_id FROM products WHERE prod_id = 'DTNTR');

使用自连接的方式:
SELECT
p1.prod_id,
p1.prod_name
FROM
products AS p1,
products AS p2
WHERE
p1.vend_id = p2.vend_id
AND
p2.prod_id = 'DTNTR';
10
 
1
SELECT
2
  p1.prod_id,
3
  p1.prod_name
4
FROM
5
  products AS p1,
6
  products AS p2
7
WHERE
8
  p1.vend_id = p2.vend_id
9
  AND
10
  p2.prod_id = 'DTNTR';

2.2 自然连接 NATURAL JOIN

我们在说到内连接,即等值连接的时候,会返回所有的数据,甚至相同的列多次出现。

而自然连接,就是排除了那些多次出现的列,使每个列只返回一次。即“自然连接”和“内连接”的区别,在于对“重合的相同的部分”处理方式不同:
  • "natural join 自然连接" 的处理方式:既然重复了,就丢掉一份,好比distinct
  • “inner join 内连接” 的处理方式:虽然重复,但两份都保留

2.3 外部连接 LEFT/RIGHT OUTER JOIN

许多连接是将一个表中的行,与另一个表中的行相关联,某些情况下需要包含没有关联行的行,这时候就要用到外部连接。

简单来说,一般的如自然连接和等值连接,两个表中只有相互匹配的行才会组成新的行放在结果表中,没有匹配的行不论在第一个表还是在第二个表它最终都会信息丢失,不会出现在最终的结果表中。而外部连接,就可以保留这部分信息。

如为了检索所有客户,包括那些没有订单的客户,可以用如下:
SELECT
customers.cust_id,
orders.order_num
FROM
customers LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;
5
 
1
SELECT
2
  customers.cust_id,
3
  orders.order_num
4
FROM
5
  customers LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;

使用OUTER JOIN语法时,必须使用RIGHT或LEFT,两者的区别在于,以哪边的表为主。例如左连接,在结果表中,则左边表的行全部保留,而右边表的行则是以是否满足自然连接为依据,不匹配的会丢失。



3、组合查询 UNION

我们大多数的操作,都是从一个或多个表返回数据的单条SELECT语句。

MySQL允许我们执行多条SELECT语句,而把它们的结果作为单个查询结果集返回。这样的组合查询通常称之为并(union)或复合查询(compound query)。

UNION的使用很简单,只需要给出每条SELECT语句,并在各条之间放上关键字UNION。

如下例,需要价格小于等于5的所有物品的列表,而且还想包括供应商1001和1002生产的所有物品(不考虑价格),当然你可以使用WHERE子句来完成,这里我们使用UNION:
(
SELECT
vend_id,
prod_id,
prod_price
FROM
products
WHERE
prod_price <= 5
)
UNION
(
SELECT
vend_id,
prod_id,
prod_price
FROM
products
WHERE
vend_id IN (1001, 1002)
);
21
 
1
(
2
SELECT
3
  vend_id,
4
  prod_id,
5
  prod_price
6
FROM
7
  products
8
WHERE
9
  prod_price <= 5
10
)
11
UNION
12
(
13
SELECT
14
  vend_id,
15
  prod_id,
16
  prod_price
17
FROM
18
  products
19
WHERE
20
  vend_id IN (1001, 1002)
21
);

当然,如果用WHERE子句的话,方式如下:
SELECT
vend_id,
prod_id,
prod_price
FROM
products
WHERE
prod_price <= 5
OR
vend_id IN (1001, 1002);
 
1
SELECT
2
  vend_id,
3
  prod_id,
4
  prod_price
5
FROM
6
  products
7
WHERE
8
  prod_price <= 5
9
  OR
10
  vend_id IN (1001, 1002);

在这个例子中,UNION可能使用起来更复杂,但是对于更复杂的过滤条件,或者从多个表(而不是单个表)中检索数据的情形,使用UNION可能会使处理更简单,逻辑更清晰。

另,使用UNION有几条规则需要注意:
  • UNION必须由两条或以上的SELECT语句组成
  • 每个查询必须包含相同的列、表达式或聚集函数
  • 列数据类型必须兼容
  • UNION会默认自动取消各SELECT结果中重复多余的结果,如果需要保留,使用UNION ALL关键字
  • 结果集无法出现一部分使用一种方式排序,另一部分使用其他方式排序,只能使用一条ORDER BY


《MySQL必知必会》[02] 多表联合查询的更多相关文章

  1. 《MySQL必知必会》官方提供的数据库和表

    数据用于配合<MySQL必知必会>(MySQL Crash Course)这本书使用,配套SQL文件也可在Ben Forta网站下载. Ben Forta网址:http://forta.c ...

  2. MySQL必知必会-官方数据库表及SQL脚本导入生成

    最近在复习SQL语句,看的是MySQL必知必会这本书,但是发现附录中只有表设计,没有表的具体数据.所以在学习相应的语句中体验不是很好,去网上查了数据库的内容,自己慢慢导入到了数据库中.把表放出来作为参 ...

  3. mysql学习--mysql必知必会1

     例如以下为mysql必知必会第九章開始: 正則表達式用于匹配特殊的字符集合.mysql通过where子句对正則表達式提供初步的支持. keywordregexp用来表示后面跟的东西作为正則表達式 ...

  4. mysql学习--mysql必知必会

      上图为数据库操作分类:     下面的操作參考(mysql必知必会) 创建数据库 运行脚本建表: mysql> create database mytest; Query OK, 1 row ...

  5. MySQL使用和操作总结(《MySQL必知必会》读书笔记)

    简介 MySQL是一种DBMS,即它是一种数据库软件.DBMS可分为两类:一类是基于共享文件系统的DBMS,另一类是基于客户机——服务器的DBMS.前者用于桌面用途,通常不用于高端或更关键应用. My ...

  6. django基础之day04,必知必会13条,双下划线查询,字段增删改查,对象的跨表查询,双下划线的跨表查询

    from django.test import TestCase # Create your tests here. import os import sys if __name__ == " ...

  7. 《MySQL 必知必会》读书总结

    这是 <MySQL 必知必会> 的读书总结.也是自己整理的常用操作的参考手册. 使用 MySQL 连接到 MySQL shell>mysql -u root -p Enter pas ...

  8. 《MySQL必知必会》[01] 基本查询

    <MySQL必知必会>(点击查看详情) 1.写在前面的话 这本书是一本MySQL的经典入门书籍,小小的一本,也受到众多网友推荐.之前自己学习的时候是啃的清华大学出版社的计算机系列教材< ...

  9. mysql必知必会系列(一)

    mysql必知必会系列是本人在读<mysql必知必会>中的笔记,方便自己以后查看. MySQL. Oracle以及Microsoft SQL Server等数据库是基于客户机-服务器的数据 ...

随机推荐

  1. 【Ubuntu 16】启动Eclipse Indigo报错 error code1 jdk没有配置好

    在/etc/profile下配置好JAVA_HOME CLASSPATH PATH 这些变量后 eclipse启动jvm并不能直接按照这些变量来启动 需要使用命令 update-alternative ...

  2. hadoop系列四:mapreduce的使用(二)

    转载请在页首明显处注明作者与出处 一:说明 此为大数据系列的一些博文,有空的话会陆续更新,包含大数据的一些内容,如hadoop,spark,storm,机器学习等. 当前使用的hadoop版本为2.6 ...

  3. Win10个性化设置

    Win10个性化设置.. ---------------------- Capture001-我的桌面 ---------------------- Win10设置任务栏的颜色 ----------- ...

  4. 7.21.04 for循环

    for循环的三个语句可以放置任何表达式,但是有个不成文的规则,for循环的3个部分应当对同一个计数器变量进行初始化,检测和更新.若不遵循这一规则,编写的循环常常晦涩难懂! 如果在循环第一部分声明了一个 ...

  5. python+selenium自动化软件测试(第14章):基础实战(1)

    #coding=utf- from selenium import webdriven from selenium.webdriver.common.by import By from seleniu ...

  6. Java开发相关命名规范

    JAVA文件命名规范 1.类命名 抽象类以 Abstract 或者 Base 开头.异常类以 Exception 作为后缀.枚举类以 Enum 作为后缀.工具类以 Utils 作为后缀(相应的包名最后 ...

  7. 【拦截器】HandlerInterceptor接口

    package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax. ...

  8. 关于本地代码挂载到vm虚拟环境下运行

    第一步: 首先你得装个 VM 虚拟机  然后新建一个Linux虚拟环境(建议CentOS镜像)(PS:至于安装此处就省略.....) 第二步:启动虚拟机配置 lnmp (这里我们可以使用 lnmp的 ...

  9. 实现CA证书创建及客户端申请证书

    author:JevonWei 版权声明:原创作品 CA证书的相关文件路径 openssl配置文件/etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf C ...

  10. import和require

    es6 的 import 语法跟 require 不同,而且 import 必须放在文件的最开始,且前面不允许有其他逻辑代码,这和其他所有编程语言风格一致. import不同与require,它是编译 ...