1. SQL连接的几种方式图例
zhuanlan.zhihu.com/p/442228986…
zhuanlan.zhihu.com/p/604188137…
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;
1.1.2 LEFT JOIN(左外连接) :
含义: 返回左表中的所有行,以及右表中与左表中行匹配的行。如果右表中没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 LEFT JOIN table2 ON table1.column = table2.column;
1.1.3 RIGHT JOIN(右外连接) :
含义: 返回右表中的所有行,以及左表中与右表中行匹配的行。如果左表中没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 RIGHT JOIN table2 ON table1.column = table2.column;
1.1.4 FULL JOIN(全外连接) :
含义: 返回左右两表中的所有行,以及两表中连接列的值相等的行。如果某一边没有匹配的行,将显示 NULL 值。
语法: SELECT * FROM table1 FULL JOIN table2 ON table1.column = table2.column;
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 样例表的模型
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