MySQL在字段中使用select子查询
一、前言
这篇文章是对另一位大神的文章进行观点证实和补充的,源地址:
我们先看看网上大神怎么描述的,
大概的形式是这样的:
select a .*,(select b.another_field from b where a.id=b.aid) another_field from a where 1 limit 10;
下面还是以实例来说明,要不然不好理解,新建两张表,一张是商品表,另外一张是商品的评论表
商品表:
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(30) CHARACTER SET utf8 NOT NULL,
`price` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
评论表:
CREATE TABLE `comment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entity_id` int(11) NOT NULL,
`content` varchar(100) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
然后插入一些数据:
INSERT INTO `product` (`id`, `product_name`, `price`) VALUES
(1, '肉松饼', 5),
(2, '可乐', 5),
(3, '鸡翅', 12),
(4, '杯子', 42);
INSERT INTO `comment` (`id`, `entity_id`, `content`) VALUES
(1, 1, '味道还不错'),
(2, 1, '还行啊'),
(3, 3, '很实用哦');
下面我们用子查询的方式来查出商品的信息以及每个商品的评论数量
SELECT product.*,
(select count(comment.id) from comment where product.id=comment.entity_id) comment_count FROM `product` limit 5;
查询结果:
id | product_name | price | comment_count |
1 | 肉松本 | 5 | 2 |
2 | 可乐 | 5 | 0 |
3 | 鸡翅 | 12 | 1 |
4 | 杯子 | 42 | 0 |
对于这种查询,可以分成两部来理解,首先忽略整个select子查询,查出商品表中的数据。
- 根据商品的id执行子查询,对于一个商品id,子查询只能返回一条数据,如果子查询返回多条数据则会出错。
- 每一条select子查询只能查询一个字段。
二、自己的解析
先记住上面2点,我自己来慢慢剖析
首先,我们从观点1可得,子查询就是拿着主表中的一条记录的id去查自己表的数据,那么
(select count(comment.id) from comment where product.id=comment.entity_id)
我可以转化成:
select count(*) from comment c,product p where c.entity_id=p.id and p.id=?
其中的?就是通过主表(product)查出来的每行记录中的id值,然后把查出来的count添加到主表中的查询结果中的最后一列。(也就是我上一个结果表中的comment_count列)
三、深入证明作者的2个观点
从“自己的解析”中,我并没有证明2个观点,那么我们在举个例子:
查出每个商品信息以及商品的最新评论内容
SELECT product.*,
(select comment.content
from comment
where product.id=comment.entity_id
order by comment.id desc limit 1
) comment_count
FROM `product` limit 5;
结果:
id | product_name | price | last_comment |
1 | 肉松本 | 5 | 还行啊 |
2 | 可乐 | 5 | NULL |
3 | 鸡翅 | 12 | 很实用哦 |
4 | 杯子 | 42 | NULL |
我同样的,把子查询给变个样子
select c.content
from comment c,product p
where p.id=c.entity_id
order by c.id desc limit 1
- 如果我在自己变形后的子查询中多添加一个字段c.id,是不会报错,且能查询出2个字段的记录的。
content id
很使用哦 3
但是在真正的子查询中多添加这个字段c.id,则报错。[Err] 1241 - Operand should contain 1 column(s)
。则证实了观点二:每一条select子查询只能查询一个字段。 - 我当时在想
order by c.id desc limit 1
是干嘛的,就是为了控制输出的数据只能是一个,当我把limit改为2,则报错:[Err] 1242 - Subquery returns more than 1 row
。这也证实了观点1。