MySQL 子查询

MySQL支持将一个查询语句嵌套在另一个查询语句中,嵌套在另一个查询语句中的SQL语句就是子查询语句。

目录

数据表

商品表

新增商品数据

商品分类表

新增商品分类数据

MySQL 子查询

ANY子查询

ALL子查询

EXISTS子查询

NOT EXISTS子查询

IN子查询

NOT IN子查询

子查询作为结果字段

总结


数据表

准备示例数据表及数据

商品表

创建商品表,创建SQL如下:

CREATE TABLE `t_goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `t_category_id` int(11) DEFAULT NULL,
  `t_category` varchar(30) DEFAULT NULL,
  `t_name` varchar(50) DEFAULT NULL,
  `t_price` decimal(10,2) DEFAULT NULL,
  `t_stock` int(11) DEFAULT NULL,
  `t_upper_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `foreign_category` (`t_category_id`)
)

新增商品数据

新增商品表测试数据,SQL如下:

INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (1, 1, '女装/女士精品', 'T恤', 39.90, 1000, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (2, 1, '女装/女士精品', '连衣裙', 79.90, 2500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (3, 1, '女装/女士精品', '卫衣', 89.90, 1500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (4, 1, '女装/女士精品', '牛仔裤', 89.90, 3500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (5, 1, '女装/女士精品', '百褶裙', 29.90, 500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (6, 1, '女装/女士精品', '呢绒外套', 399.90, 1200, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (7, 2, '户外运动', '自行车', 399.90, 1000, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (8, 2, '户外运动', '山地自行车', 1399.90, 2500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (9, 2, '户外运动', '登山杖', 59.90, 1500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (10, 2, '户外运动', '骑行装备', 399.90, 3500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (11, 2, '户外运动', '运动外套', 799.90, 500, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (12, 2, '户外运动', '滑板', 499.90, 1200, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (13, 5, '水果', '葡萄', 49.90, 1000, '2025-08-14 00:00:00');
INSERT INTO `t_goods` (`id`, `t_category_id`, `t_category`, `t_name`, `t_price`, `t_stock`, `t_upper_time`) VALUES (14, 5, '水果', '香蕉', 39.90, 1000, '2025-08-14 00:00:00');

商品分类表

创建商品分类表,创建SQL如下:

CREATE TABLE `t_goods_category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `t_category` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

新增商品分类数据

新增商品分类表测试数据,SQL如下:

INSERT INTO `t_goods_category` (`id`, `t_category`) VALUES (1, '女装/女士精品');
INSERT INTO `t_goods_category` (`id`, `t_category`) VALUES (2, '户外运动');
INSERT INTO `t_goods_category` (`id`, `t_category`) VALUES (3, '男装');
INSERT INTO `t_goods_category` (`id`, `t_category`) VALUES (4, '童装');
INSERT INTO `t_goods_category` (`id`, `t_category`) VALUES (5, '水果');

MySQL 子查询

子查询语句可以添加到SELECT、UPDATE和DELETE语句中,常用的操作符包括ANY、SOME、ALL、EXISTS、NOT EXISTS、IN和NOT IN等。

ANY子查询

ANY关键字表示如果与子查询返回的任何值相匹配,则返回TRUE,否则返回FALSE。

例:查询t_goods数据表中t_category_id字段值大于t_goods_category数据表中任意一个id字段值的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods WHERE t_category_id > ANY (SELECT id FROM t_goods_category); 
+----+---------------+------------+------------+---------+
| id | t_category_id | t_category | t_name     | t_price |
+----+---------------+------------+------------+---------+
|  7 |             2 | 户外运动   | 自行车     | 399.90  |
|  8 |             2 | 户外运动   | 山地自行车 | 1399.90 |
|  9 |             2 | 户外运动   | 登山杖     | 59.90   |
| 10 |             2 | 户外运动   | 骑行装备   | 399.90  |
| 11 |             2 | 户外运动   | 运动外套   | 799.90  |
| 12 |             2 | 户外运动   | 滑板       | 499.90  |
| 13 |             5 | 水果       | 葡萄       | 49.90   |
| 14 |             5 | 水果       | 香蕉       | 39.90   |
+----+---------------+------------+------------+---------+
8 rows in set (0.04 sec)

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods WHERE t_category_id > SOME (SELECT id FROM t_goods_category); 
+----+---------------+------------+------------+---------+
| id | t_category_id | t_category | t_name     | t_price |
+----+---------------+------------+------------+---------+
|  7 |             2 | 户外运动   | 自行车     | 399.90  |
|  8 |             2 | 户外运动   | 山地自行车 | 1399.90 |
|  9 |             2 | 户外运动   | 登山杖     | 59.90   |
| 10 |             2 | 户外运动   | 骑行装备   | 399.90  |
| 11 |             2 | 户外运动   | 运动外套   | 799.90  |
| 12 |             2 | 户外运动   | 滑板       | 499.90  |
| 13 |             5 | 水果       | 葡萄       | 49.90   |
| 14 |             5 | 水果       | 香蕉       | 39.90   |
+----+---------------+------------+------------+---------+
8 rows in set (0.04 sec)

注意:SOME子查询的作用与ANY子查询的作用相同,不再赘述。

ALL子查询

ALL关键字表示如果同时满足所有子查询的条件,则返回TRUE,否则返回FALSE。

例:查询t_goods数据表中t_category_id字段值大于t_goods_category数据表中所有id字段值的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods  WHERE t_category_id > ALL (SELECT id FROM t_goods_category);
Empty set

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods  WHERE t_category_id > ALL (SELECT id FROM t_goods_category where id < 5);
+----+---------------+------------+--------+---------+
| id | t_category_id | t_category | t_name | t_price |
+----+---------------+------------+--------+---------+
| 13 |             5 | 水果       | 葡萄   | 49.90   |
| 14 |             5 | 水果       | 香蕉   | 39.90   |
+----+---------------+------------+--------+---------+
2 rows in set (0.05 sec)

EXISTS子查询

EXISTS关键字表示如果存在某种条件,则返回TRUE,否则返回FALSE。

例:查询t_goods_category数据表中是否存在id为2的数据,如果存在,则查询t_goods数据表中t_category_id为2的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods WHERE EXISTS (SELECT t_category FROM t_goods_category WHERE id = 2) AND t_category_id = 2;
+----+---------------+------------+------------+---------+
| id | t_category_id | t_category | t_name     | t_price |
+----+---------------+------------+------------+---------+
|  7 |             2 | 户外运动   | 自行车     | 399.90  |
|  8 |             2 | 户外运动   | 山地自行车 | 1399.90 |
|  9 |             2 | 户外运动   | 登山杖     | 59.90   |
| 10 |             2 | 户外运动   | 骑行装备   | 399.90  |
| 11 |             2 | 户外运动   | 运动外套   | 799.90  |
| 12 |             2 | 户外运动   | 滑板       | 499.90  |
+----+---------------+------------+------------+---------+
6 rows in set (0.04 sec)

NOT EXISTS子查询

NOT EXISTS关键字表示如果不存在某种条件,则返回TRUE,否则返回FALSE。

例:查询t_goods_category数据表中是否不存在id为6的数据,如果不存在,则查询t_goods数据表中t_category_id为1的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods WHERE NOT EXISTS ( SELECT t_category FROM t_goods_category WHERE id = 6 ) AND t_category_id = 1;
+----+---------------+---------------+----------+---------+
| id | t_category_id | t_category    | t_name   | t_price |
+----+---------------+---------------+----------+---------+
|  1 |             1 | 女装/女士精品 | T恤      | 39.90   |
|  2 |             1 | 女装/女士精品 | 连衣裙   | 79.90   |
|  3 |             1 | 女装/女士精品 | 卫衣     | 89.90   |
|  4 |             1 | 女装/女士精品 | 牛仔裤   | 89.90   |
|  5 |             1 | 女装/女士精品 | 百褶裙   | 29.90   |
|  6 |             1 | 女装/女士精品 | 呢绒外套 | 399.90  |
+----+---------------+---------------+----------+---------+
6 rows in set (0.04 sec)

IN子查询

IN关键字表示如果比较的数据在IN列表中,则返回TRUE,否则返回FALSE。

例:查询t_goods_category数据表中名称为“户外运动”的id数据,并根据查询出的id数据查询t_goods数据表中的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price FROM t_goods  WHERE t_category_id IN ( SELECT id FROM t_goods_category WHERE t_category = '户外运动');
+----+---------------+------------+------------+---------+
| id | t_category_id | t_category | t_name     | t_price |
+----+---------------+------------+------------+---------+
|  7 |             2 | 户外运动   | 自行车     | 399.90  |
|  8 |             2 | 户外运动   | 山地自行车 | 1399.90 |
|  9 |             2 | 户外运动   | 登山杖     | 59.90   |
| 10 |             2 | 户外运动   | 骑行装备   | 399.90  |
| 11 |             2 | 户外运动   | 运动外套   | 799.90  |
| 12 |             2 | 户外运动   | 滑板       | 499.90  |
+----+---------------+------------+------------+---------+
6 rows in set (0.05 sec)

NOT IN子查询

NOT IN关键字表示如果比较的数据不在IN列表中,则返回TRUE,否则返回FALSE。

例:查询t_goods_category数据表中名称为“女装/女士精品”的id数据,并查询t_goods数据表中不在id列表中的数据。

mysql> SELECT id, t_category_id, t_category, t_name, t_price  FROM t_goods WHERE t_category_id NOT IN (  SELECT id FROM t_goods_category  WHERE t_category = '户外运动' );
+----+---------------+---------------+----------+---------+
| id | t_category_id | t_category    | t_name   | t_price |
+----+---------------+---------------+----------+---------+
|  1 |             1 | 女装/女士精品 | T恤      | 39.90   |
|  2 |             1 | 女装/女士精品 | 连衣裙   | 79.90   |
|  3 |             1 | 女装/女士精品 | 卫衣     | 89.90   |
|  4 |             1 | 女装/女士精品 | 牛仔裤   | 89.90   |
|  5 |             1 | 女装/女士精品 | 百褶裙   | 29.90   |
|  6 |             1 | 女装/女士精品 | 呢绒外套 | 399.90  |
| 13 |             5 | 水果          | 葡萄     | 49.90   |
| 14 |             5 | 水果          | 香蕉     | 39.90   |
+----+---------------+---------------+----------+---------+
8 rows in set (0.05 sec)

子查询作为结果字段

MySQL支持使用子查询的结果数据作为最终查询结果的某一列数据。

例:查询t_goods_category数据表中的数据,并统计每个商品类别下的商品数量。

mysql> SELECT category.id, category.t_category, (SELECT COUNT(*) FROM t_goods goods WHERE goods.t_category_id = category.id) AS goods_count FROM t_goods_category category;
+----+---------------+-------------+
| id | t_category    | goods_count |
+----+---------------+-------------+
|  1 | 女装/女士精品 |           6 |
|  2 | 户外运动      |           6 |
|  3 | 男装          |           0 |
|  4 | 童装          |           0 |
|  5 | 水果          |           2 |
+----+---------------+-------------+
5 rows in set (0.05 sec)

可以看到,使用子查询统计t_goods_category数据表中每个商品类别下的商品数量,并作为最终结果的goods_count字段的数据进行输出。

总结

简单介绍了MySQL中常用子查询和子查询用法及相应示例。

### MySQL 子查询的使用方法和示例 MySQL 中的子查询(Subquery)是指嵌套在另一个 SQL 查询语句中的查询。它通常用于实现更复杂的逻辑,帮助主查询引用从子查询中计算出的结果。根据返回结果的不同形式,子查询可以分为标量子查询、多行子查询、多列子查询以及相关子查询。 #### 标量子查询 标量子查询返回单个值,可以作为表达式的一部分用于主查询的条件判断或计算。例如,假设有一个 `orders` 表记录订单信息,一个 `products` 表记录产品信息,可以通过子查询获取某个产品的平均价格,并在主查询中使用: ```sql SELECT order_id, product_id, price FROM orders WHERE price > (SELECT AVG(price) FROM products WHERE product_type = 'Electronics'); ``` 此查询会筛选出价格高于电子产品平均价格的所有订单[^1]。 #### 多行子查询 多行子查询返回多个值,通常与 `IN`, `NOT IN`, `ANY`, 或 `ALL` 等操作符一起使用。例如,查找所有销售量高于特定产品类别的产品: ```sql SELECT product_id, name FROM products WHERE sales > ANY(SELECT sales FROM products WHERE category = 'Books'); ``` 这将选择出销售量大于任意一本书籍销量的产品[^1]。 #### 多列子查询 多列子查询返回多个列的数据,通常用于匹配多个字段。例如,查找具有特定属性组合的记录: ```sql SELECT customer_id, order_date FROM orders WHERE (customer_id, order_date) IN ( SELECT customer_id, MAX(order_date) FROM orders GROUP BY customer_id ); ``` 这段代码会选择每个客户的最新订单日期对应的记录[^1]。 #### 相关子查询 相关子查询是依赖于外部查询值的子查询。它对于每一行数据都会执行一次子查询。例如,找出每个部门工资最高的员工: ```sql SELECT e.name, e.salary, e.department_id FROM employees e WHERE e.salary = ( SELECT MAX(salary) FROM employees WHERE department_id = e.department_id ); ``` 在这个例子中,内部查询依赖于外部查询中的 `department_id` 来确定每个部门的最大工资。 #### EXISTS 子查询 `EXISTS` 子查询用于测试子查询是否至少会返回一行数据。这种类型的查询经常用来检查是否存在满足特定条件的记录。例如,验证是否存在未完成的订单: ```sql SELECT customer_id, name FROM customers WHERE EXISTS ( SELECT 1 FROM orders WHERE status != 'Completed' AND customer_id = customers.customer_id ); ``` 如果客户有未完成的订单,则该客户的信息会被选中[^3]。 通过这些不同类型的子查询,开发者可以根据具体需求设计出灵活且强大的查询逻辑。合理利用子查询不仅可以简化复杂的数据检索任务,还能提高数据库查询的整体效率[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JSON_L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值