SQL连接查询详解

在数据库操作中,连接查询是一种常用的数据检索方式,它允许从两个或多个表中检索数据。本文将详细介绍SQL中的各种连接查询方式,并通过示例数据展示它们的区别和使用场景。

创建示例临时表

为了说明连接查询的概念,首先创建两个临时表,并在其中插入特定的行。这些临时表将用于演示不同类型的连接查询。

表TEMP_A包含四行数据,ID分别为1、2、3、4。表TEMP_B包含五行数据,ID分别为1、2、3、3、5。注意,表A中的第3行在表B中出现了两次,而第4行在表B中没有对应的行,同时表B中有一个孤儿行(第5行),在表A中没有对应的行。

内连接(Inner Join)

内连接查询将返回两个表中ID字段值相同的行。使用示例数据,可以得到以下结果:

SELECT * FROM TEMP_A INNER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
1 Tbl A Row 1 1 Tbl B Row 1
2 Tbl A Row 2 2 Tbl B Row 2
3 Tbl A Row 3 3 Tbl B Row 3a
3 Tbl A Row 3 3 Tbl B Row 3b

注意,表A中的第3行在表B中对应了两个不同的行,因此在结果中被重复了两次。

左连接(Left Join)

左连接查询不仅返回两个表中ID字段值相同的行,还会返回左表中没有在右表中找到对应行的行。使用示例数据,可以得到以下结果:

SELECT * FROM TEMP_A LEFT OUTER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
1 Tbl A Row 1 1 Tbl B Row 1
2 Tbl A Row 2 2 Tbl B Row 2
3 Tbl A Row 3 3 Tbl B Row 3a
3 Tbl A Row 3 3 Tbl B Row 3b
4 Tbl A Row 4 NULL NULL

注意,表A中的第4行在表B中没有对应的行,因此表B的所有字段都显示为NULL。

右连接(Right Join)

右连接查询与左连接查询类似,但它返回的是右表中没有在左表中找到对应行的行。使用示例数据,可以得到以下结果:

SELECT * FROM TEMP_A RIGHT OUTER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
1 Tbl A Row 1 1 Tbl B Row 1
2 Tbl A Row 2 2 Tbl B Row 2
3 Tbl A Row 3 3 Tbl B Row 3a
3 Tbl A Row 3 3 Tbl B Row 3b
NULL NULL 5 Tbl B Row 5

注意,表B中的第5行在表A中没有对应的行,因此表A的所有字段都显示为NULL。

全连接(Full Join)

全连接查询是左连接和右连接的结合,它返回两个表中ID字段值相同的行,以及左表中没有在右表中找到对应行的行和右表中没有在左表中找到对应行的行。使用示例数据,可以得到以下结果:

SELECT * FROM TEMP_A FULL OUTER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
1 Tbl A Row 1 1 Tbl B Row 1
2 Tbl A Row 2 2 Tbl B Row 2
3 Tbl A Row 3 3 Tbl B Row 3a
3 Tbl A Row 3 3 Tbl B Row 3b
4 Tbl A Row 4 NULL NULL
NULL NULL 5 Tbl B Row 5

全连接查询的结果包含了所有可能的组合,包括两个表中ID字段值相同的行,以及各自独有的行。

交叉连接(Cross Join)

交叉连接查询不指定连接字段,它将返回表A中的每一行与表B中的每一行的组合。使用示例数据,可以得到以下结果:

SELECT * FROM TEMP_A, TEMP_B;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data

交叉连接的结果数量将是两个表行数的乘积,因此会产生大量的数据。

为什么不应该使用非唯一键

在本例中,使用了具有唯一值的表A中的TBL_ID字段进行连接。如果连接键在两个表中都不是唯一的,那么非唯一键将导致交叉连接。让向表A添加一行数据来展示这一点。

INSERT INTO TEMP_A VALUES (3, 'Tbl A Row 3 dup');

然后执行内连接查询:

SELECT * FROM TEMP_A INNER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
1 Tbl A Row 1 1 Tbl B Row 1
2 Tbl A Row 2 2 Tbl B Row 2
3 Tbl A Row 3 3 Tbl B Row 3a
3 Tbl A Row 3 3 Tbl B Row 3b
3 Tbl A Row 3 dup 3 Tbl B Row 3a
3 Tbl A Row 3 dup 3 Tbl B Row 3b

可以看到,由于表A中的TBL_ID字段现在不是唯一的,得到了6行结果,这实际上是一个交叉连接。

使用连接查询选择孤儿行

如何获取一个表中没有另一个表中对应行的所有行?通过左连接或右连接,并使用WHERE子句来移除不需要的行。

使用示例数据:

SELECT * FROM TEMP_A LEFT OUTER JOIN TEMP_B ON TEMP_A.Tbl_ID = TEMP_B.Tbl_ID WHERE TEMP_B.Tbl_ID IS NULL;

结果如下:

Tbl_ID Tbl_Data Tbl_ID Tbl_Data
4 Tbl A Row 4 NULL NULL

通过这种方式,可以得到表A中没有在表B中找到对应行的所有行。

CREATE TABLE TEMP_A ( Tbl_ID INT NOT NULL, Tbl_Data VARCHAR(50) NOT NULL ); INSERT INTO TEMP_A VALUES (1, 'Tbl A Row 1'); INSERT INTO TEMP_A VALUES (2, 'Tbl A Row 2'); INSERT INTO TEMP_A VALUES (3, 'Tbl A Row 3'); INSERT INTO TEMP_A VALUES (4, 'Tbl A Row 4'); CREATE TABLE TEMP_B ( Tbl_ID INT NOT NULL, Tbl_Data VARCHAR(50) NOT NULL ); INSERT INTO TEMP_B VALUES (1, 'Tbl B Row 1'); INSERT INTO TEMP_B VALUES (2, 'Tbl B Row 2'); INSERT INTO TEMP_B VALUES (3, 'Tbl B Row 3a'); INSERT INTO TEMP_B VALUES (3, 'Tbl B Row 3b'); INSERT INTO TEMP_B VALUES (5, 'Tbl B Row 5');
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485