菜鸟教程 -- 学的不仅是技术,更是梦想!

SQL 教程
(追記) (追記ここまで)

SQL 连接(JOIN)


SQL join 用于把来自两个或多个表的行结合起来。

下图展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法。

类型描述
INNER JOIN返回两个表中满足连接条件的记录(交集)。
LEFT JOIN返回左表中的所有记录,即使右表中没有匹配的记录(保留左表)。
RIGHT JOIN返回右表中的所有记录,即使左表中没有匹配的记录(保留右表)。
FULL OUTER JOIN返回两个表的并集,包含匹配和不匹配的记录。
CROSS JOIN返回两个表的笛卡尔积,每条左表记录与每条右表记录进行组合。
SELF JOIN将一个表与自身连接。
NATURAL JOIN基于同名字段自动匹配连接的表。

示例数据

表1:Customers

CustomerID Name
1 Alice
2 Bob
3 Charlie

表2:Orders

OrderID CustomerID Product
101 1 Laptop
102 2 Phone
103 4 Tablet

各连接结果对比

JOIN 类型 结果
INNER JOIN 返回两个表中匹配的记录。在给定的例子中,只有 CustomerID 为 1 和 2 的记录在两个表中都有匹配,所以只会返回这些记录。
LEFT JOIN 返回左表(Customers)中的所有记录,即使右表(Orders)中没有匹配的记录。对于左表中没有匹配的右表记录,结果中的右表字段将为 NULL。在例子中,CustomerID 为 3 的记录在右表中没有匹配,所以其对应的 Product 将为 NULL。
RIGHT JOIN 返回右表(Orders)中的所有记录,即使左表(Customers)中没有匹配的记录。对于右表中没有匹配的左表记录,结果中的左表字段将为 NULL。在例子中,OrderID 为 103 的记录在左表中没有匹配,所以其对应的 Name 将为 NULL。
FULL OUTER JOIN 返回两个表中的所有记录,无论它们是否匹配。如果某个表中没有匹配的记录,那么该表的字段将为 NULL。在例子中,CustomerID 为 3 和 OrderID 为 103 的记录将分别在对方的表中显示为 NULL。
CROSS JOIN 返回两个表的笛卡尔积,即左表中的每一行与右表中的每一行组合。在例子中,每个顾客都将与每个订单组合,产生多个结果。
SELF JOIN 表与其自身进行连接。这通常用于查询表中相互关联的记录,比如员工与其经理之间的关系。

SQL JOIN

SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。

最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN)。 SQL INNER JOIN 从多个表中返回满足 JOIN 条件的所有行。

语法:

SELECT column1, column2, ...
FROM table1
JOIN table2 ON condition;

参数说明:

  • column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。
  • table1:要连接的第一个表。
  • table2:要连接的第二个表。
  • condition:连接条件,用于指定连接方式。

演示数据库

在本教程中,我们将使用 RUNOOB 样本数据库。

下面是选自 "Websites" 表的数据:

+----+--------------+---------------------------+-------+---------+
| id | name | url | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1 | Google | https://www.google.cm/ | 1 | USA |
| 2 | 淘宝 | https://www.taobao.com/ | 13 | CN |
| 3 | 菜鸟教程 | http://www.runoob.com/ | 4689 | CN |
| 4 | 微博 | http://weibo.com/ | 20 | CN |
| 5 | Facebook | https://www.facebook.com/ | 3 | USA |
| 7 | stackoverflow | http://stackoverflow.com/ | 0 | IND |
+----+---------------+---------------------------+-------+---------+

下面是 "access_log" 网站访问记录表的数据:

mysql> SELECT * FROM access_log;
+-----+---------+-------+------------+
| aid | site_id | count | date |
+-----+---------+-------+------------+
| 1 | 1 | 45 | 2016年05月10日 |
| 2 | 3 | 100 | 2016年05月13日 |
| 3 | 1 | 230 | 2016年05月14日 |
| 4 | 2 | 10 | 2016年05月14日 |
| 5 | 5 | 205 | 2016年05月14日 |
| 6 | 4 | 13 | 2016年05月15日 |
| 7 | 3 | 220 | 2016年05月15日 |
| 8 | 5 | 545 | 2016年05月16日 |
| 9 | 3 | 201 | 2016年05月17日 |
+-----+---------+-------+------------+
9 rows in set (0.00 sec)

请注意,"Websites" 表中的 "id" 列指向 "access_log" 表中的字段 "site_id"。上面这两个表是通过 "site_id" 列联系起来的。

然后,如果我们运行下面的 SQL 语句(包含 INNER JOIN):

实例

SELECT Websites.id, Websites.name, access_log.count, access_log.date
FROM Websites
INNER JOIN access_log
ON Websites.id=access_log.site_id;

执行以上 SQL 输出结果如下:



不同的 SQL JOIN

在我们继续讲解实例之前,我们先列出您可以使用的不同的 SQL JOIN 类型:

  • INNER JOIN:如果表中有至少一个匹配,则返回行
  • LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN:只要其中一个表中存在匹配,则返回行
AI 思考中...

3 篇笔记 写笔记

  1. #0

    Roam

    275***[email protected]

    429

    首先,连接的结果可以在逻辑上看作是由SELECT语句指定的列组成的新表。

    左连接与右连接的左右指的是以两张表中的哪一张为基准,它们都是外连接。

    外连接就好像是为非基准表添加了一行全为空值的万能行,用来与基准表中找不到匹配的行进行匹配。假设两个没有空值的表进行左连接,左表是基准表,左表的所有行都出现在结果中,右表则可能因为无法与基准表匹配而出现是空值的字段。

    这部分主要涉及的是表连接的逻辑问题,教程主讲语法的话这部分确实需要自己再去搜资料

    来源:《数据库系统原理教程》,王珊,陈红编著,P86

    Roam

    275***[email protected]

    9年前 (2017年09月12日)
  2. #0

    悠闲的某某某

    jim***[email protected]

    160

    得到的结果数:

    inner join <= min(left join, right join)
    full join >= max(left join, right join)
    当 inner join < min(left join, right join) 时, full join > max(left join, right join)

    悠闲的某某某

    jim***[email protected]

    8年前 (2018年05月03日)
  3. #0

    辣条

    421***[email protected]

    110

    MySQL 暂不支持 FULL JOIN, 要实现完全外部链接需要额外处理。

    -- MySQL实现完全外部链接,要使用 UNION 将一个左链接、和一个右链接去重合并。

    SELECT a.*,b.*
    FROM 表1 a LEFT JOIN 表2 b
    ON a.unit_NO = b.unit_NO
    UNION
    SELECT a.*,b.*
    FROM 表1 a RIGHT JOIN 表2 b
    ON a.unit_NO = b.unit_NO;

    辣条

    421***[email protected]

    6年前 (2020年09月18日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /