SQL - 左连接
- SQL 左连接
- 使用左连接连接多个表
- 带 WHERE 子句的左连接
- 使用 LEFT JOIN 的别名
- 关于 SQL LEFT JOIN 的重要要点
SQL 左连接
SQL 中的 LEFT JOIN(或 LEFT OUTER JOIN)将两个或多个表中的行组合起来,返回左表中的所有行以及右表中匹配的行。
如果右表中没有匹配项,结果仍然会包含左表的行,但右表的所有列将显示为 NULL 值。
SQL LEFT JOIN 的 Venn 图
下面的 Venn 图展示了 SQL LEFT JOIN 中两个表之间的关系:
如果第一个表的行数少于第二个表的行数,则第二个表中没有在第一个表中对应项的行将被从结果中丢弃。
语法
以下是 SQL 中 Left Join 的基本语法:
SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1.column_name = table2.column_name;
示例
为了更好地理解这个查询,让我们在现有数据库中创建一些表,并使用 Left Join 或 Left Outer Join 连接它们。
假设我们已经使用以下查询创建了一个名为 CUSTOMERS 的表,其中包含客户的个人信息,包括姓名、年龄、地址和薪资。
CREATE TABLE CUSTOMERS ( ID INT NOT NULL, NAME VARCHAR (20) NOT NULL, AGE INT NOT NULL, ADDRESS CHAR (25), SALARY DECIMAL (18, 2), PRIMARY KEY (ID) );
现在使用 INSERT 语句向该表插入值,如下所示:
INSERT INTO CUSTOMERS VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 ), (2, 'Khilan', 25, 'Delhi', 1500.00 ), (3, 'Kaushik', 23, 'Kota', 2000.00 ), (4, 'Chaitali', 25, 'Mumbai', 6500.00 ), (5, 'Hardik', 27, 'Bhopal', 8500.00 ), (6, 'Komal', 22, 'Hyderabad', 4500.00 ), (7, 'Muffy', 24, 'Indore', 10000.00 );
表将创建如下:
| ID | NAME | AGE | ADDRESS | SALARY |
|---|---|---|---|---|
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | Kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | Hyderabad | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
让我们创建另一个表 ORDERS,其中包含订单详情和订单日期。
CREATE TABLE ORDERS ( OID INT NOT NULL, DATE VARCHAR (20) NOT NULL, CUSTOMER_ID INT NOT NULL, AMOUNT DECIMAL (18, 2) );
使用 INSERT 语句向该表插入值,如下所示:
INSERT INTO ORDERS VALUES (102, '2009-10-08 00:00:00', 3, 3000.00), (100, '2009-10-08 00:00:00', 3, 1500.00), (101, '2009-11-20 00:00:00', 2, 1560.00), (103, '2008-05-20 00:00:00', 4, 2060.00);
表显示如下:
| OID | DATE | CUSTOMER_ID | AMOUNT |
|---|---|---|---|
| 102 | 2009-10-08 00:00:00 | 3 | 3000.00 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500.00 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560.00 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060.00 |
以下 left join query,检索在指定日期下订单的客户详情以及没有下订单的客户。如果没有找到匹配项,下面的查询将在该记录中返回 NULL。
SELECT ID, NAME, AMOUNT, DATE FROM CUSTOMERS LEFT JOIN ORDERS ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
结果表如下所示:
| ID | NAME | AMOUNT | DATE |
|---|---|---|---|
| 1 | Ramesh | NULL | NULL |
| 2 | Khilan | 1560.00 | 2009-11-20 00:00:00 |
| 3 | Kaushik | 1500.00 | 2009-10-08 00:00:00 |
| 3 | Kaushik | 3000.00 | 2009-10-08 00:00:00 |
| 4 | Chaitali | 2060.00 | 2008-05-20 00:00:00 |
| 5 | Hardik | NULL | NULL |
| 6 | Komal | NULL | NULL |
| 7 | Muffy | NULL | NULL |
如上表所示,只有 Khilan、Kaushik 和 Chaitali 在 ORDERS 表中提到的日期进行了购买,因此这些记录匹配。CUSTOMERS 表中的其他客户在指定日期没有进行购买,因此这些记录返回为 NULL。
使用 Left Join 连接多个表
类似于 INNER JOIN,LEFT JOIN 也可以用于连接多个表。第一个(最左边的)表的行会原样返回,而其余表会与第一个表的行进行匹配。如果其他表中不存在匹配的行,则会为它们的列返回 NULL 值。
语法
使用 Left Join 连接多个表的语法如下所示:
SELECT
left_table.column1,
left_table.column2,
right_table.column1,
right_table.column2
FROM left_table
LEFT JOIN right_table
ON
left_table.common_column = right_table.common_column;
示例
为了演示使用多个表的 Left Join,我们考虑之前创建的 CUSTOMERS 和 ORDERS 表。此外,我们将使用以下查询创建 EMPLOYEE 表:
CREATE TABLE EMPLOYEE ( EID INT NOT NULL, EMPLOYEE_NAME VARCHAR (30) NOT NULL, SALES_MADE DECIMAL (20) );
现在,我们可以使用 INSERT 语句向这个空表插入值,如下所示:
INSERT INTO EMPLOYEE VALUES (102, 'SARIKA', 4500), (100, 'ALEKHYA', 3623), (101, 'REVATHI', 1291), (103, 'VIVEK', 3426);
EMPLOYEE 表包含组织中员工的详细信息以及他们完成的销售额。
| EID | EMPLOYEE_NAME | SALES_MADE |
|---|---|---|
| 102 | SARIKA | 4500 |
| 100 | ALEKHYA | 3623 |
| 101 | REVATHI | 1291 |
| 103 | VIVEK | 3426 |
以下查询使用 left join 连接 CUSTOMERS、ORDERS 和 EMPLOYEE 表:
SELECT CUSTOMERS.ID, CUSTOMERS.NAME, ORDERS.DATE, EMPLOYEE.EMPLOYEE_NAME FROM CUSTOMERS LEFT JOIN ORDERS ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID LEFT JOIN EMPLOYEE ON ORDERS.OID = EMPLOYEE.EID;
通过此查询,我们将显示客户的 id 和 name,以及订单制作的日期和销售该物品的员工姓名。
结果表如下所示:
| ID | NAME | DATE | EMPLOYEE_NAME |
|---|---|---|---|
| 1 | Ramesh | NULL | NULL |
| 2 | Khilan | 2009-11-20 00:00:00 | REVATHI |
| 3 | Kaushik | 2009-10-08 00:00:00 | ALEKHYA |
| 3 | Kaushik | 2009-10-08 00:00:00 | SARIKA |
| 4 | Chaitali | 2008-05-20 00:00:00 | VIVEK |
| 5 | Hardik | NULL | NULL |
| 6 | Komal | NULL | NULL |
| 7 | Muffy | NULL | NULL |
如上表所示,客户 Kaushik 下了三笔订单,其中两笔由员工 Alekhya 销售,一笔由 Sarika 销售。Khilan 和 Chaitali 各下一笔订单,分别由 Revathi 和 Vivek 销售。这些订单制作的日期也会显示。如果在特定日期没有下订单,则返回 NULL。
带有 WHERE 子句的 Left Join
您可以使用 WHERE 子句与 LEFT JOIN 一起过滤连接后的结果。LEFT JOIN 确保返回左表的所有行,而 WHERE 子句可以对左表或右表应用额外的条件。
请注意,如果在 WHERE 子句中仅检查右表的非 NULL 值,则过滤右表可能会将 LEFT JOIN 转换为 INNER JOIN。
语法
与 WHERE 子句一起使用 Left Join 的语法如下所示:
SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1.column_name = table2.column_name WHERE condition;
示例
考虑之前的两个表 CUSTOMERS 和 ORDERS;使用 left join 查询连接它们,并使用 WHERE 子句应用一些约束。
SELECT ID, NAME, DATE, AMOUNT FROM CUSTOMERS LEFT JOIN ORDERS ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID WHERE ORDERS.AMOUNT > 2000.00;
应用 where 子句与 left join 后的结果表包含金额值大于 2000.00 的行:
| ID | NAME | DATE | AMOUNT |
|---|---|---|---|
| 3 | Kaushik | 2009-10-08 00:00:00 | 3000.00 |
| 4 | Chaitali | 2008-05-20 00:00:00 | 2060.00 |
使用 LEFT JOIN 的别名
SQL 允许你在 LEFT JOIN 查询中为表分配别名。别名是临时的名称,可以使你的查询更容易阅读和编写,尤其是在处理多个表或长表名时。
语法
以下是在 SQL 中使用 LEFT JOIN 的别名的语法:
SELECT c.NAME, o.AMOUNT, o.DATE FROM CUSTOMERS AS c LEFT JOIN ORDERS AS o ON c.ID = o.CUSTOMER_ID;
示例
在这个示例中,我们为 CUSTOMERS 使用别名 c,为 ORDERS 使用别名 o,并检索客户名称以及订单金额和日期:
SELECT c.NAME, o.AMOUNT, o.DATE FROM CUSTOMERS AS c LEFT JOIN ORDERS AS o ON c.ID = o.CUSTOMER_ID;
结果表与使用完整表名相同,但当涉及多个 JOIN 时,查询更容易阅读:
| NAME | AMOUNT | DATE |
|---|---|---|
| Ramesh | NULL | NULL |
| Khilan | 1560 | 2009-11-20 00:00:00 |
| Kaushik | 1500 | 2009-10-08 00:00:00 |
| Kaushik | 3000 | 2009-10-08 00:00:00 |
| Chaitali | 2060 | 2008-05-20 00:00:00 |
| Hardik | NULL | NULL |
| Komal | NULL | NULL |
| Muffy | NULL | NULL |
关于 SQL LEFT JOIN 的重要要点
以下是使用 SQL 中的 LEFT JOIN 应该了解的一些重要要点:
- 左表的所有行都会返回:即使右表中没有匹配的行,左表的数据也会显示。
- 右表列可能包含 NULL:如果在右表中找不到匹配的行,对应的列将显示
NULL。 - LEFT JOIN 可以链式使用:你可以在单个查询中使用多个 LEFT JOIN 来连接多个表。
- 别名简化查询:为表名使用别名可以使复杂查询更短、更易阅读。
- 使用 WHERE 过滤:如果在右表上使用 WHERE 子句过滤非 NULL 值,可能会无意中将 LEFT JOIN 转为 INNER JOIN。
- 表的顺序很重要:首先列出的表始终是“左”表;交换顺序会改变结果。
- LEFT JOIN 与 INNER JOIN 的区别:与 INNER JOIN 不同,LEFT JOIN 会保留左表中未匹配的行,这使其适用于查找缺失或可选数据。