在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.上面的案例其实也可以用 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)动态计算结果。