SQL 连接方式学习记录

118 阅读5分钟

1. SQL连接的几种方式图例

zhuanlan.zhihu.com/p/442228986…
zhuanlan.zhihu.com/p/604188137…

image.png

1.1 SQL中常见的连接方式及其含义:

SQL 允许在 JOIN 左边加上一些修饰性的关键词,从而形成不同类型的连接,如下表所示:

连接类型说明
INNER JOIN(默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。
LEFT JOIN返回左表中的所有行,即使右表中没有满足条件的行也是如此。
RIGHT JOIN返回右表中的所有行,即使左表中没有满足条件的行也是如此。
FULL JOIN只要其中有一个表存在满足条件的记录,就返回行。
SELF JOIN将一个表连接到自身,就像该表是两个表一样。为了区分两个表,在 SQL 语句中需要至少重命名一个表。
CROSS JOIN交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。

1.1.1 INNER JOIN(内连接)

含义: 返回两个表中互相匹配的行,即两个表中连接列的值相等的行。
语法: SELECT * FROM table1 INNER JOIN table2 ON table1.column = table2.column;

image.png

1.1.2 LEFT JOIN(左外连接)

含义: 返回左表中的所有行,以及右表中与左表中行匹配的行。如果右表中没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 LEFT JOIN table2 ON table1.column = table2.column;

image.png

1.1.3 RIGHT JOIN(右外连接)

含义: 返回右表中的所有行,以及左表中与右表中行匹配的行。如果左表中没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 RIGHT JOIN table2 ON table1.column = table2.column;

image.png

1.1.4 FULL JOIN(全外连接)

含义: 返回左右两表中的所有行,以及两表中连接列的值相等的行。如果某一边没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 FULL JOIN table2 ON table1.column = table2.column;

image.png

1.1.5 CROSS JOIN(交叉连接)

含义: 返回两个表的笛卡尔积,即左表的每一行与右表的每一行组合在一起。
语法: SELECT * FROM table1 CROSS JOIN table2;

1.1.6 SELF JOIN(自连接)

含义: 表示连接表中的行与该表中的其他行,常用于表示具有层次结构的数据。
语法: SELECT * FROM table1 t1 INNER JOIN table1 t2 ON t1.column = t2.column;

2. 样例数据和模型图

2.1 样例sql

-- 创建 customers 表  
CREATE TABLE test_for_join.customers  
(  
customer_id INT PRIMARY KEY,  
customer_name VARCHAR(50),  
email VARCHAR(50)  
);  
  
-- 插入数据到 customers 表  
INSERT INTO test_for_join.customers  
VALUES (101, 'John Doe', 'john@example.com');  
INSERT INTO test_for_join.customers  
VALUES (102, 'Jane Smith', 'jane@example.com');  
INSERT INTO test_for_join.customers  
VALUES (103, 'Bob Johnson', 'bob@example.com');  
  
-- 创建 orders 表  
CREATE TABLE test_for_join.orders  
(  
order_id INT PRIMARY KEY,  
customer_id INT,  
order_date DATE  
);  
  
-- 插入数据到 orders 表  
INSERT INTO test_for_join.orders  
VALUES (1, 101, '2023-01-01');  
INSERT INTO test_for_join.orders  
VALUES (2, 102, '2023-01-02');  
INSERT INTO test_for_join.orders  
VALUES (3, 103, '2023-01-03');  
  
-- 创建 products 表  
CREATE TABLE test_for_join.products  
(  
product_id INT PRIMARY KEY,  
product_name VARCHAR(50),  
category_id INT,  
price DECIMAL(10, 2)  
);  
  
-- 插入数据到 products 表  
INSERT INTO test_for_join.products  
VALUES (1, 'Laptop', 1, 1200.00);  
INSERT INTO test_for_join.products  
VALUES (2, 'Smartphone', 1, 800.00);  
INSERT INTO test_for_join.products  
VALUES (3, 'Tablet', 1, 400.00);  
INSERT INTO test_for_join.products  
VALUES (4, 'Headphones', 2, 100.00);  
INSERT INTO test_for_join.products  
VALUES (5, 'Printer', 3, 300.00);  
  
-- 创建 categories 表  
CREATE TABLE test_for_join.categories  
(  
category_id INT PRIMARY KEY,  
category_name VARCHAR(50)  
);  
  
-- 插入数据到 categories 表  
INSERT INTO test_for_join.categories  
VALUES (1, 'Electronics');  
INSERT INTO test_for_join.categories  
VALUES (2, 'Audio');  
INSERT INTO test_for_join.categories  
VALUES (3, 'Printers');  
  
-- 创建 order_items 表  
CREATE TABLE test_for_join.order_items  
(  
order_item_id INT PRIMARY KEY,  
order_id INT,  
product_id INT,  
quantity INT  
);  
  
-- 插入数据到 order_items 表  
INSERT INTO test_for_join.order_items  
VALUES (1, 1, 1, 2);  
INSERT INTO test_for_join.order_items  
VALUES (2, 1, 4, 1);  
INSERT INTO test_for_join.order_items  
VALUES (3, 2, 2, 1);  
INSERT INTO test_for_join.order_items  
VALUES (4, 3, 5, 3);  
  
-- 添加一些存在差异的数据到 customers 表  
INSERT INTO test_for_join.customers  
VALUES (104, 'Eva Green', 'eva@example.com');  
  
-- 添加一些存在差异的数据到 orders 表  
INSERT INTO test_for_join.orders  
VALUES (6, 105, '2023-01-06');  
  
-- 添加一些存在差异的数据到 products 表  
INSERT INTO test_for_join.products  
VALUES (6, 'Camera', 1, 700.00);  
  
-- 添加一些存在差异的数据到 categories 表  
INSERT INTO test_for_join.categories  
VALUES (4, 'Photography');  
  
-- 添加一些存在差异的数据到 order_items 表  
INSERT INTO test_for_join.order_items  
VALUES (5, 4, 6, 2);

2.2 样例表的模型

image.png

3. sql连接样例

INNER JOIN

SELECT test_for_join.customers.customer_id, test_for_join.customers.customer_name, test_for_join.orders.order_id, test_for_join.orders.order_date  
FROM test_for_join.customers  
INNER JOIN test_for_join.orders ON customers.customer_id = orders.customer_id;

执行结果:

customer_id | customer_name | order_id | order_date
------------+---------------+----------+------------
101         | John Doe      | 1        | 2023-01-01
102         | Jane Smith    | 2        | 2023-01-02
103         | Bob Johnson   | 3        | 2023-01-03

LEFT JOIN

SELECT test_for_join.customers.customer_id, test_for_join.customers.customer_name, test_for_join.orders.order_id, test_for_join.orders.order_date  
FROM test_for_join.customers  
LEFT JOIN test_for_join.orders ON customers.customer_id = orders.customer_id;

执行结果:

customer_id | customer_name | order_id | order_date
------------+---------------+----------+------------
101         | John Doe      | 1        | 2023-01-01
102         | Jane Smith    | 2        | 2023-01-02
103         | Bob Johnson   | 3        | 2023-01-03
104         | Eva Green     | null     | null

RIGHT JOIN

SELECT test_for_join.customers.customer_id, customers.customer_name, orders.order_id, orders.order_date  
FROM test_for_join.customers  
RIGHT JOIN test_for_join.orders ON customers.customer_id = orders.customer_id;

执行结果:

customer_id | customer_name | order_id | order_date
------------+---------------+----------+------------
null        | null          | 6        | 2023-01-06
101         | John Doe      | 1        | 2023-01-01
102         | Jane Smith    | 2        | 2023-01-02
103         | Bob Johnson   | 3        | 2023-01-03

FULL JOIN (如果数据库支持)

SELECT test_for_join.customers.customer_id, customers.customer_name, orders.order_id, orders.order_date  
FROM test_for_join.customers  
FULL JOIN test_for_join.orders ON customers.customer_id = orders.customer_id;

执行结果(在某些数据库中可能不支持FULL JOIN,这时可以使用LEFT JOIN和RIGHT JOIN的UNION操作代替)。

customer_id | customer_name | order_id | order_date
------------+---------------+----------+------------
null        | null          | 6        | 2023-01-06
101         | John Doe      | 1        | 2023-01-01
102         | Jane Smith    | 2        | 2023-01-02
103         | Bob Johnson   | 3        | 2023-01-03
104         | Eva Green     | null     | null

UNION

SELECT product_name, product_id FROM test_for_join.products  
UNION  
SELECT category_name, category_id FROM test_for_join.categories;

执行结果:

product_name | product_id
------------+---------------
Audio        | 2
Camera       | 6
Electronics  | 1
Headphones   | 4
Laptop       | 1
Photography  | 4
Printer      | 5
Printers     | 3
Smartphone   | 2
Tablet       | 3