MySQL执行查询时报Subquery returns more than 1 row如何解决
报错原因
你遇到的报错是因为recent_images对应的子查询返回了多行多列的结果,而SQL中的标量子查询仅允许返回单行单列的值,因此触发了Subquery returns more than 1 row错误。除此之外你的原SQL还有两处语法问题:
users.name字段后缺少逗号分隔符- LEFT JOIN关联条件的表名写错,
followers.followee实际应为follow.followee
解决方案
MySQL 8.0支持窗口函数和JSON聚合函数,可以满足你返回指定JSON结构的需求,完整可用的SQL如下:
SELECT u.name, -- 统计该关注对象的总图片数量 (SELECT COUNT(*) FROM images WHERE user_id = f.followee) AS total_images, -- 拼接最近3张图片的JSON数组,无图片时返回空数组 IFNULL(JSON_ARRAYAGG( JSON_OBJECT( 'id', i.id, 'path', i.path ) ), JSON_ARRAY()) AS recent_images FROM follow f LEFT JOIN users u ON f.followee = u.id -- 关联过滤出每个用户的最近3张图片 LEFT JOIN ( SELECT id, user_id, path, -- 对每个用户的图片按创建时间倒序排名 ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY createdAt DESC) AS rn FROM images ) i ON f.followee = i.user_id AND i.rn <= 3 WHERE f.follower = 2 GROUP BY f.followee, u.name;
如果你需要直接返回符合你示例格式的完整JSON串,可以使用如下写法:
SELECT JSON_ARRAYAGG( JSON_OBJECT( 'name', u.name, 'total_images', (SELECT COUNT(*) FROM images WHERE user_id = f.followee), 'recent_images', IFNULL(i.recent_imgs, JSON_ARRAY()) ) ) AS result FROM follow f LEFT JOIN users u ON f.followee = u.id LEFT JOIN ( SELECT user_id, JSON_ARRAYAGG(JSON_OBJECT('id', id, 'path', path)) AS recent_imgs FROM ( SELECT id, user_id, path, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY createdAt DESC) AS rn FROM images ) t WHERE rn <=3 GROUP BY user_id ) i ON f.followee = i.user_id WHERE f.follower = 2;
逻辑说明
- 用
ROW_NUMBER()窗口函数给每个用户的图片按创建时间倒序排序,筛选rn<=3的记录即可得到每个用户的最近3张图片 - 用
JSON_OBJECT()将单张图片的id和path拼接为要求的对象格式,再用JSON_ARRAYAGG()将多个图片对象聚合为数组,得到recent_images字段 - 总图片数通过独立的子查询统计,避免被最近3条的过滤条件影响
- 新增
IFNULL判断,当关注对象没有上传图片时,recent_images返回空数组而非null
内容的提问来源于stack exchange,提问作者Rabby hossain
相关产品推荐
相关产品推荐

