SQL 查询数据:使用子查询

在SQL查询中,子查询是一种强大的工具,它允许我们在一个查询内部嵌套另一个查询,将内层查询的结果作为外层查询的条件、数据源或计算依据。本文将聚焦子查询的核心应用场景 —— 利用子查询进行过滤和作为计算字段使用子查询,通过具体案例带你从基础理解到实战应用。

  

什么是子查询

子查询(也叫嵌套查询),指的是嵌套在另一个 SELECT、INSERT、UPDATE 或 DELETE 语句中的 SELECT 语句。内层查询的结果会传递给外层查询,帮助外层查询更精准地获取数据。

子查询的核心特点:

  • 内层查询先于外层查询执行(“先算内层,再用外层”);

  • 通常用括号 () 包裹,明确子查询的范围;

  • 根据返回结果的行数和列数,可分为 “单行子查询”、“多行子查询” 和 “多列子查询”。

   

利用子查询进行过滤

利用子查询进行过滤,是子查询最常用的场景之一。核心逻辑是先用子查询获取一个 “条件集合”(比如某个分类的 ID、某个价格区间的商品 ID),再将这个集合作为外层查询的过滤条件,最终筛选出目标数据。

注意,子查询可以作为 WHERE 子句的条件,配合 IN、NOT IN、=、> 等运算符使用。

单行子查询:过滤单个条件

当子查询返回单行单列结果时,属于单行子查询,可配合 =、>、< 等比较运算符使用。

示例:查询名为 ”红米K70“ 的商品的订单信息,先使用子查询获取名为 "红米K70" 商品的 ID,然后商品 ID 查询订单列表。如下:

> select * from order_product op where op.product_id = (select product_id from product where name='红米K70')

order_product_id|order_id|product_id|quantity|product_price|create_time        |update_time        |
----------------+--------+----------+--------+-------------+-------------------+-------------------+
               4|       3|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              16|      15|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              23|      20|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|

3 row(s) fetched.

注意:单行子查询必须确保内层查询只返回 1 行结果,否则会报错(比如用 = 匹配多行数据)。

多行子查询:过滤多个条件

当子查询返回多行单列结果时,属于多行子查询,需配合 IN(匹配任意一个)、NOT IN(不匹配任何一个)、ANY、ALL 等运算符使用。

示例:查询名称为 “红米K70”、 “小米14手机”' 和 “一加12” 商品对应的订单信息,如下:

-- 子查询:查询名称为 '红米K70', '小米14手机', '一加12' 商品的 ID
> select product_id from product where name in ('红米K70', '小米14手机', '一加12')

product_id|
----------+
         1|
         7|
         8|

3 row(s) fetched.

-- 使用子查询查询这些商品
> select * from order_product op 
where op.product_id in (select product_id from product where name in ('红米K70', '小米14手机', '一加12'))

order_product_id|order_id|product_id|quantity|product_price|create_time        |update_time        |
----------------+--------+----------+--------+-------------+-------------------+-------------------+
               1|       1|         1|       1|      4999.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
               3|       2|         1|       1|      4999.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              13|      12|         1|       1|      4999.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
               4|       3|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              16|      15|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              23|      20|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              11|      10|         8|       1|      4599.00|2025-12-24 14:44:13|2025-12-24 14:44:13|

7 row(s) fetched.

子查询过滤 vs 联表查询:怎么选?

上面的案例其实也可以用 JOIN 联表查询实现,比如 “示例 1” 的联表写法:

> select op.* from order_product op 
join product p on p.product_id=op.product_id
where p.name='红米K70'

order_product_id|order_id|product_id|quantity|product_price|create_time        |update_time        |
----------------+--------+----------+--------+-------------+-------------------+-------------------+
               4|       3|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              16|      15|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|
              23|      20|         7|       1|      2499.00|2025-12-24 14:44:13|2025-12-24 14:44:13|

3 row(s) fetched.

两者的区别与选择建议:

  • 联表查询(JOIN):适合需要同时显示两个表的字段,性能上通常更优(数据库对 JOIN 优化更好)。

  • 子查询过滤:适合只需要显示一个表的字段,逻辑更直观(先找条件,再查数据),代码可读性更高,适合初学者。

  

子查询作为计算字段使用

除了过滤条件,子查询还可以作为 “计算字段”,嵌套在 SELECT 子句中。核心逻辑是:对于外层查询的每一行数据,都通过子查询计算出一个对应的结果(比如某个分类的商品数量、某个商品的价格排名),并将这个结果作为一个新的字段显示。

注意:作为计算字段的子查询,必须返回单行单列结果(因为每一行数据只能对应一个计算值)。

示例:使用子查询统计每个产品的订单数量

> select p.product_id, p.name, p.price, 
    (select count(*) from order_product op where op.product_id=p.product_id) as order_count  -- 子查询,统计商品的订单数
from product p 

product_id|name        |price  |order_count|
----------+------------+-------+-----------+
         1|小米14手机      |4999.00|          3|
         2|华为Mate60 Pro|6999.00|          3|
         3|苹果iPhone 15 |7999.00|          2|
         4|vivo X100   |3999.00|          3|
         5|OPPO Find X7|4499.00|          2|
         6|荣耀Magic6    |4299.00|          2|
         7|红米K70       |2499.00|          3|
         8|一加12        |4599.00|          1|
         9|真我GT Neo5   |2599.00|          2|
        10|三星S24 Ultra |8999.00|          2|

10 row(s) fetched.

说明:上面示例的子查询 (select count(*) from order_product op where op.product_id=p.product_id) 引用了外层查询的表(product p),会根据外层表的每一行数据(每个 product_id)动态计算结果。

  

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