MySQL支持将一个查询语句嵌套在另一个查询语句中,嵌套在另一个查询语句中的SQL语句就是子查询语句。
目录
数据表
准备示例数据表及数据
商品表
创建商品表,创建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中常用子查询和子查询用法及相应示例。