域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

连接

本章将讨论 PostgreSQL 的各种连接:内连接、左外连接、右外连接、交叉连接、自然连接、自连接和完全外连接。值得一提的是,哪怕到了 MySQL 8,MySQL 依然不支持完全外连接。

开始之前,先创建两张表并插入一些数据:

CREATE TABLE basket_a (
    a INT PRIMARY KEY,
    fruit_a VARCHAR (100) NOT NULL
);

CREATE TABLE basket_b (
    b INT PRIMARY KEY,
    fruit_b VARCHAR (100) NOT NULL
);

INSERT INTO basket_a (a, fruit_a)
VALUES
    (1, 'Apple'),
    (2, 'Orange'),
    (3, 'Banana'),
    (4, 'Cucumber');

INSERT INTO basket_b (b, fruit_b)
VALUES
    (1, 'Orange'),
    (2, 'Apple'),
    (3, 'Watermelon'),
    (4, 'Pear');

内连接

SELECT
    a,
    fruit_a,
    b,
    fruit_b
FROM
    basket_a
INNER JOIN basket_b
    ON fruit_a = fruit_b;
  • 使用 INNER JOIN 进行连接,使用 ON 指定连接条件
  • 内连接检查第一个表(basket_a)中每一行,并与第二个表(basket_b)的每一行进行对比:如果指定字段的值相等(由 ON 指定的 fruit_afruit_b),则创建新行,并将该行添加到结果集中。

左外连接

  • 使用 LEFT JOIN 进行连接,使用 ON 指定条件
    • LEFT JOIN 左侧的表为“左表”,此例中的 basket_a
    • LEFT JOIN 右侧的表为“右表”,此例中的 basket_b
  • 从左表(basket_a)中选择数据,并将它的 fruit_a字段的值和右表(basket_b)的 fruit_b 字段值进行对比(由 ON 指定):
    • 如果相等,将创建一个包含两张表记录的新行,并将新行添加到结果集中
    • 如果不相等,只创建只包含左表记录,右边记录全部为 NULL 的新行,并将新行添加到结果集中
  • LEFT JOIN 左侧的表为“左表”,此例中的 basket_a
  • LEFT JOIN 右侧的表为“右表”,此例中的 basket_b
  • 如果相等,将创建一个包含两张表记录的新行,并将新行添加到结果集中
  • 如果不相等,只创建只包含左表记录,右边记录全部为 NULL 的新行,并将新行添加到结果集中

LEFT JOINLEFT OUTER JOIN 的简写

LEFT JOINLEFT OUTER JOIN 的简写

右外连接

SELECT
    a,
    fruit_a,
    b,
    fruit_b
FROM
    basket_a
RIGHT JOIN basket_b ON fruit_a = fruit_b;

全外连接

SELECT
    a,
    fruit_a,
    b,
    fruit_b
FROM
    basket_a
FULL OUTER JOIN basket_b 
    ON fruit_a = fruit_b;

生成多个表中,所有记录的笛卡尔积。

  • 没有 ON 指定条件
  • 这是一个非常耗费资源的操作
SELECT 字段列表 FROM t1 CROSS JOIN t1;

-- 等价于
SELECT 字段列表 FROM t1,t2;

-- 使用INNER JOIN模拟:ON的条件始终为真
SELECT 字段列表 FROM t1 INNER JOIN t2 ON 1=1;

自然连接

基于连接表中,相同字段名创建的隐式连接。

比如,示例数据库中,city表和country 表都有 country_id 字段 :

SELECT * FROM city NATURAL INNER JOIN country;
  • 预期将隐式使用两个表中的同名字段 country_id 进行连接
  • 实际结果确是空结果,原因是两个表中还有一个同名字段 last_update

自连接

所谓自连接,是指连接两方都是同一张表,常用应用场景是父子分类。

SELECT FROM 字段列表 FROM 表 AS t1 INNER JOIN 表 AS t2 ON t1.字段名1 = t2.字段名2; 

示例:

CREATE TABLE employee (
	employee_id INT PRIMARY KEY,
	first_name VARCHAR (255) NOT NULL,
	last_name VARCHAR (255) NOT NULL,
	manager_id INT,
	FOREIGN KEY (manager_id) 
	REFERENCES employee (employee_id) 
	ON DELETE CASCADE
);
INSERT INTO employee (
	employee_id,
	first_name,
	last_name,
	manager_id
)
VALUES
	(1, 'Windy', 'Hays', NULL),
	(2, 'Ava', 'Christensen', 1),
	(3, 'Hassan', 'Conner', 1),
	(4, 'Anna', 'Reeves', 2),
	(5, 'Sau', 'Norman', 2),
	(6, 'Kelsie', 'Hays', 3),
	(7, 'Tory', 'Goff', 3),
	(8, 'Salley', 'Lester', 3);
	
SELECT
    e.first_name || ' ' || e.last_name AS employee,
    m.first_name || ' ' || m.last_name AS manager
FROM
    employee AS e
INNER JOIN employee AS m ON m.employee_id = e.manager_id
ORDER BY manager;
要查看完整内容,请先登录