SQL 查询数据:创建高级表联结

在 SQL 查询中,当需要从多个表中获取数据时,“表别名” 和 “联结(JOIN)” 是两个核心且高频的技术点。表别名能简化 SQL 语句,消除列歧义,提升可读性。而各类联结则是实现多表关联查询的基础,直接决定了我们能否高效、准确地获取跨表数据。

本文将围绕表别名、不同类型联结(自联结、自然联结、外部联结等)、带聚集函数的联结及联结条件展开,结合实例详细讲解其用法与应用场景。

使用表别名

表别名是给查询中的表起一个简短的 “昵称”,主要作用是简化 SQL 语句、消除列歧义,尤其在多表查询或表名较长时,能大幅提升编写效率和可读性。

给表起别名的语法非常简单,在表名后直接添加别名,中间可加关键字 AS(也可省略),语法如下:

-- 语法格式
SELECT 列名 FROM 表名 [AS] 别名;

-- 多表查询中使用
SELECT 别名1.列名, 别名2.列名 FROM 表名1 [AS] 别名1 
JOIN 表名2 [AS] 别名2 ON 联结条件;

示例:现有两张表,product(商品表,含 product_id、name、price、stock、category_id 字段)和 product_category(商品分类表,含 category_id、name),查询商品名称及对应分类名称:

-- 如果使用*通配符,输出所有列,则有字段重复,如 category_id、create_time、update_time 字段重复
> select * from product p 
join product_category pc on p.category_id=pc.category_id
where pc.name='电脑'

product_id|name         |price   |stock|category_id|create_time        |update_time        |category_id|name|create_time        |update_time        |
----------+-------------+--------+-----+-----------+-------------------+-------------------+-----------+----+-------------------+-------------------+
        13|联想拯救者Y9000P  | 8999.00|  300|          3|2025-01-02 01:49:00|2025-12-31 03:18:08|          3|电脑  |2025-12-31 03:18:08|2025-12-31 03:18:08|
        14|苹果MacBook Pro  |12999.00|  180|          3|2025-01-11 19:36:00|2025-12-31 03:18:08|          3|电脑  |2025-12-31 03:18:08|2025-12-31 03:18:08|

2 row(s) fetched.


-- 不使用表别名(较繁琐)
> select product.name as '商品名称', product_category.name as '分类名称' from product
join product_category on product.category_id=product_category.category_id
where product_category.name='电脑'

商品名称         |分类名称|
-----------------+----+
联想拯救者Y9000P  |电脑  |
苹果MacBook Pro  |电脑  |

2 row(s) fetched.

-- 使用表别名(简洁清晰)
> select p.name as '商品名称', pc.name as '分类名称' from product p
join product_category pc on p.category_id=pc.category_id
where pc.name='电脑'

商品名称         |分类名称|
----------------+----+
联想拯救者Y9000P  |电脑  |
苹果MacBook Pro  |电脑  |

2 row(s) fetched.

说明:示例中用 p 作为 product 的别名,pc 作为 product_category 的别名,语句更简洁,且通过别名明确了 category_id 来自哪张表。

不同类型的联结(JOIN)

联结的本质是通过 “共同字段”(关联键)将多个表的数据组合成一个结果集。根据数据匹配规则的不同,SQL 提供了多种联结类型,核心包括内联结、自联结、自然联结、外部联结等。以下结合实例逐一介绍。

内联结(INNER JOIN):只取匹配的数据

内联结是最常用的联结类型,它只返回两个表中 “关联键匹配成功” 的数据行,不匹配的行将被过滤。

语法如下:

SELECT 列名 FROM 表1 别名1 INNER JOIN 表2 别名2 ON 别名1.关联键 = 别名2.关联键;

示例:查询每个商品的名称和分类名称,只显示有对应分类信息的商品

> select p.name as '商品名称', pc.name as '分类名称' from product p
join product_category pc on p.category_id=pc.category_id

商品名称         |分类名称|
-------------+----+
小米14手机       |手机  |
华为Mate60 Pro |手机  |
苹果iPhone 15  |手机  |
vivo X100    |手机  |
OPPO Find X7 |手机  |
荣耀Magic6     |手机  |
红米K70        |手机  |
一加12         |手机  |
真我GT Neo5    |手机  |
三星S24 Ultra  |手机  |
海尔双开门冰箱      |冰箱  |
美的风冷无霜冰箱     |冰箱  |
联想拯救者Y9000P  |电脑  |
苹果MacBook Pro|电脑  |
格力落地扇        |风扇  |
美的循环扇        |风扇  |

16 row(s) fetched.

说明:如果商品表中存在  category_id 为 NULL(无分类)的商品,或分类表中无对应 category_id 记录,这些商品将不会出现在结果集中。

  

自联结(Self Join):同一张表的“自我关联”

自联结并非独立的联结类型,而是一种 “特殊的多表查询” ,将同一张表当作两张不同的表来使用,通过表别名区分,实现同一表内数据的关联查询(如查询员工及其直属经理信息)。

语法核心:必须给同一张表起两个不同的别名,否则无法区分表的两次引用。

SELECT 别名1.列名, 别名2.列名
FROM 表名 别名1
JOIN 表名 别名2
ON 别名1.关联键=别名2.关联键;

实例:使用商品表作为自联结表,别名不同,通过商品 ID 自我联结。

> select p1.name, p2.price from product p1
join product p2 on p1.product_id=p2.product_id
where p2.price > 5000 and p1.name like '%苹果%'

name         |price   |
-------------+--------+
苹果iPhone 15  | 7999.00|
苹果MacBook Pro|12999.00|

2 row(s) fetched.

说明:上面的 SQL 语句 JOIN 连接的两张表都是自己,只是别名不同。

 

自然联结(NATURAL JOIN):自动匹配同名关联键

自然联结是一种 “简化的内联结”,它会自动查找两张表中 “名称和数据类型都相同的列” 作为关联键,无需手动指定ON子句。

语法如下:

SELECT 列名 FROM 表1 NATURAL JOIN 表2;

实例:使用自然联结查询商品名称、价格、库存以及分类名称

> SELECT p.name, p.price, p.stock, pc.category_name as 'categroy_name' 
FROM (
    select name, price, stock, category_id from product
) p NATURAL JOIN (
    select category_id, name as 'category_name' from product_category
) pc 
where p.price > 5000

name         |price   |stock|categroy_name|
-------------+--------+-----+-------------+
华为Mate60 Pro | 6999.00|  800|手机           |
苹果iPhone 15  | 7999.00| 1200|手机           |
三星S24 Ultra  | 8999.00|  600|手机           |
联想拯救者Y9000P  | 8999.00|  300|电脑        |
苹果MacBook Pro|12999.00|  180|电脑           |

5 row(s) fetched.

注意事项:

  • 自然联结的风险:若两张表存在多个同名但无关联意义的列(如都有create_time),会导致错误的关联匹配,因此不建议在复杂表结构中使用。

  • 自然联结默认是内联结,若需保留不匹配的数据,可使用NATURAL LEFT JOIN或NATURAL RIGHT JOIN。

  

外部联结(OUTER JOIN)

外部联结的核心是 “保留一张表的所有数据行,即使在另一张表中没有匹配的关联键”,未匹配的列将显示为 NULL。根据保留的表不同,分为左外部联结(LEFT OUTER JOIN)、右外部联结(RIGHT OUTER JOIN)和全外部联结(FULL OUTER JOIN),其中 “OUTER” 关键字可省略。

左外部联结(LEFT JOIN):保留左表所有数据

LEFT JOIN(也写作 LEFT OUTER JOIN,OUTER 可省略)的核心作用是保留左表的所有行,即使右表中没有匹配的记录;右表无匹配时,其字段值显示为 NULL。如下图:

image.png

语法如下:

SELECT 列名 FROM 左表 别名1 
LEFT JOIN 右表 别名2 ON 别名1.关联键=别名2.关联键;

实例:查询所有商品名称和分类名称,如果分类不存在,则商品分类名称返回 NULL。注意,运行下面 SQL 前,先将分类 ID 为 4、5 的分类 ID 修改为 41、51。

> select p.name as '商品名称', p.category_id as '分类ID', pc.name as '分类名称' from product p
left join product_category pc on p.category_id=pc.category_id

商品名称         |分类ID|分类名称|
-------------+----+----+
小米14手机       |   1|手机  |
华为Mate60 Pro |   1|手机  |
苹果iPhone 15  |   1|手机  |
vivo X100    |   1|手机  |
OPPO Find X7 |   1|手机  |
荣耀Magic6     |   1|手机  |
红米K70        |   1|手机  |
一加12         |   1|手机  |
真我GT Neo5    |   1|手机  |
三星S24 Ultra  |   1|手机  |
海尔双开门冰箱      |   2|冰箱  |
美的风冷无霜冰箱     |   2|冰箱  |
联想拯救者Y9000P  |   3|电脑  |
苹果MacBook Pro|   3|电脑  |
格力落地扇        |   4|    |
美的循环扇        |   4|    |

16 row(s) fetched.

说明:左表是 product(商品表),因此所有商品都会出现在结果集中,无分类 ID(或者分类 ID 不存在) 的商品其名称为 NULL。

右外部联结(RIGHT JOIN):保留右表所有数据

RIGHT JOIN(也写作 RIGHT OUTER JOIN,OUTER 可省略)的核心逻辑与 LEFT JOIN 完全相反:保留右表的所有行,即使左表中没有匹配的记录;左表无匹配时,其字段值显示为 NULL。

image.png

注意:上图中,结果表格中 “产品名称”、“分类 ID” 属于商品表,仅仅 “分类名称” 属于分类表。

语法如下:

SELECT 列名 FROM 左表 别名1 
RIGHT JOIN 右表 别名2 ON 别名1.关联键 = 别名2.关联键;

实例:查询商品分类下所有的商品,即使分类没有商品也显示出来(为了效果将商品表分类为 4 的改为 41)。

> select p.name as '商品名称', p.category_id as '分类ID', pc.name as '分类名称' from product p
right join product_category pc on p.category_id=pc.category_id

商品名称         |分类ID|分类名称|
-------------+----+----+
三星S24 Ultra  |   1|手机  |
真我GT Neo5    |   1|手机  |
一加12         |   1|手机  |
红米K70        |   1|手机  |
荣耀Magic6     |   1|手机  |
OPPO Find X7 |   1|手机  |
vivo X100    |   1|手机  |
苹果iPhone 15  |   1|手机  |
华为Mate60 Pro |   1|手机  |
小米14手机       |   1|手机  |
美的风冷无霜冰箱     |   2|冰箱  |
海尔双开门冰箱      |   2|冰箱  |
苹果MacBook Pro|   3|电脑  |
联想拯救者Y9000P  |   3|电脑  |
             |    |风扇  |
             |    |办公桌 |

16 row(s) fetched.

  

全外部联结(FULL JOIN):保留两张表所有数据

全外部联结会保留左表和右表的所有数据行,两边不匹配的列均显示为NULL。如下图:

image.png

注意:MySQL不直接支持FULL JOIN,需用LEFT JOIN + UNION + RIGHT JOIN实现;Oracle、SQL Server 等支持。

语法如下(需要数据库支持):

SELECT 列名 FROM emp e 
FULL JOIN dept d ON e.dept_id = d.dept_id;

MySQL替代方案:

-- 左联结结果 + 右联结中左表无匹配的结果
> select p.name as '商品名称', p.category_id as '分类ID', pc.name as '分类名称' from product p
left join product_category pc on p.category_id=pc.category_id
union
select p.name as '商品名称', p.category_id as '分类ID', pc.name as '分类名称' from product p
right join product_category pc on p.category_id=pc.category_id

商品名称         |分类ID|分类名称|
-------------+----+----+
小米14手机       |   1|手机  |
华为Mate60 Pro |   1|手机  |
苹果iPhone 15  |   1|手机  |
vivo X100    |   1|手机  |
OPPO Find X7 |   1|手机  |
荣耀Magic6     |   1|手机  |
红米K70        |   1|手机  |
一加12         |   1|手机  |
真我GT Neo5    |   1|手机  |
三星S24 Ultra  |   1|手机  |
海尔双开门冰箱      |   2|冰箱  |
美的风冷无霜冰箱     |   2|冰箱  |
联想拯救者Y9000P  |   3|电脑  |
苹果MacBook Pro|   3|电脑  |
格力落地扇        |  41|    |
美的循环扇        |  41|    |
             |    |风扇  |
             |    |办公桌 |

18 row(s) fetched.

上面输出中可以看到商品包含了 NULL 信息,且分类名称也包含 NULL 值。  

  

使用带聚集函数的联结

聚集函数(如COUNT()、SUM()、AVG()等)用于对数据进行统计汇总,结合联结可实现跨表统计(如统计每个商品分类的商品数量、每个商品的订单量等)。

注意:使用聚集函数时,需配合GROUP BY分组,分组字段通常是右表的关联键(如分类 ID)。

实例:统计每个商品分类的商品数量

> select pc.category_id, pc.name, count(p.product_id) as '商品数量' 
from product_category pc 
left join product p on pc.category_id=p.category_id
group by pc.category_id, pc.name

category_id|name|商品数量|
-----------+----+----+
          1|手机  |  10|
          2|冰箱  |   2|
          3|电脑  |   2|
          4|风扇  |   0|
          5|办公桌 |   0|

5 row(s) fetched.

注意:上面 SQL 使用左联结确保所有商品分类(包括无商品的商品分类)都被统计,无商品的商品分类其商品数量为 0。

  

使用联结和联结条件

联结条件是多表查询的核心,直接决定了数据的匹配规则。错误的联结条件会导致结果集错误(如笛卡尔积、数据缺失等),以下是关于联结条件的核心注意事项:

联结条件的位置:ON 子句 与 WHERE 子句

在外部联结中,ON 子句和 WHERE 子句的作用不同,需严格区分:

  • ON子句:用于指定 “表之间的关联条件”,在联结时就过滤不匹配的数据,会保留左表(左联结)或右表(右联结)的所有行。

  • WHERE子句:用于过滤 “联结后的结果集”,会过滤掉所有不满足条件的行,包括左表/右表中本应保留的不匹配行。

实例对比:

-- 左联结,ON 子句过滤商品分类为 “电脑” 的分类(保留所有商品,仅匹配“电脑”的分类)
> SELECT p.product_id, p.name, p.price, p.stock, p.category_id, pc.name as 'category_name'
FROM product p left join product_category pc
on p.category_id=pc.category_id and pc.name='电脑'

product_id|name         |price   |stock|category_id|category_name|
----------+-------------+--------+-----+-----------+-------------+
         1|小米14手机       | 4999.00| 1000|          1|             |
         2|华为Mate60 Pro | 6999.00|  800|          1|             |
         3|苹果iPhone 15  | 7999.00| 1200|          1|             |
         4|vivo X100    | 3999.00| 1500|          1|             |
         5|OPPO Find X7 | 4499.00|  900|          1|             |
         6|荣耀Magic6     | 4299.00| 1100|          1|             |
         7|红米K70        | 2499.00| 2000|          1|             |
         8|一加12         | 4599.00|  850|          1|             |
         9|真我GT Neo5    | 2599.00| 1800|          1|             |
        10|三星S24 Ultra  | 8999.00|  600|          1|             |
        11|海尔双开门冰箱      | 3999.00|  200|          2|             |
        12|美的风冷无霜冰箱     | 2999.00|  150|          2|             |
        13|联想拯救者Y9000P  | 8999.00|  300|          3|电脑           |
        14|苹果MacBook Pro|12999.00|  180|          3|电脑           |
        15|格力落地扇        |  199.00|  500|         41|             |
        16|美的循环扇        |  299.00|  400|         41|             |

16 row(s) fetched.

-- 左联结,WHERE子句过滤商品分类为“电脑”的商品(先联结再过滤,商品分类不是“电脑”的商品均被排除)
> SELECT p.product_id, p.name, p.price, p.stock, p.category_id, pc.name as 'category_name'
FROM product p left join product_category pc
on p.category_id=pc.category_id
where pc.name='电脑'

product_id|name         |price   |stock|category_id|category_name|
----------+-------------+--------+-----+-----------+-------------+
        13|联想拯救者Y9000P  | 8999.00|  300|          3|电脑           |
        14|苹果MacBook Pro|12999.00|  180|          3|电脑           |

2 row(s) fetched.

  

避免笛卡尔积(Cartesian Product)

若忘记写联结条件,或联结条件无效(如关联键不匹配),会产生 “笛卡尔积” —— 左表的每一行都与右表的每一行匹配,结果集行数 = 左表行数 × 右表行数,通常是错误的。

错误示例(无联结条件):

-- 错误:产生笛卡尔积
> SELECT p.product_id, p.name, p.price, p.stock, p.category_id, pc.name as 'category_name'
FROM product p join product_category pc
where pc.name in ('电脑', '冰箱')

product_id|name         |price   |stock|category_id|category_name|
----------+-------------+--------+-----+-----------+-------------+
         1|小米14手机       | 4999.00| 1000|          1|电脑           |
         1|小米14手机       | 4999.00| 1000|          1|冰箱           |
         2|华为Mate60 Pro | 6999.00|  800|          1|电脑           |
         2|华为Mate60 Pro | 6999.00|  800|          1|冰箱           |
         3|苹果iPhone 15  | 7999.00| 1200|          1|电脑           |
         3|苹果iPhone 15  | 7999.00| 1200|          1|冰箱           |
...
        15|格力落地扇        |  199.00|  500|         41|电脑           |
        15|格力落地扇        |  199.00|  500|         41|冰箱           |
        16|美的循环扇        |  299.00|  400|         41|电脑           |
        16|美的循环扇        |  299.00|  400|         41|冰箱           |

32 row(s) fetched.

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号