关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法
今天在工作中写项目的时候,遇到了一个让我感到几乎无解的问题,在转换了思路后,想出了一个折中的解决方案,记录如下。
其实,问题的场景,非常简单:

就是需要查询出上图的数据,红框是从 项目产品表 中查询的2个字段,绿框是从与项目产品表关联的 文章表 中查询出的1个字段。我希望实现的效果是,获取到项目产品对应的文章提交人数,即该项目产品,有多少人提交了文章。看似很简单啊,于是我开始撸 SQL 语句了。
先写个雏形
既然在查询项目产品表的时候,希望多查询1列数据,而此列数据是从其他关联表获取的,所以基本实现方式,是使用子查询。
SELECT s.id, s.name, (SELECT COUNT(*) FROM art_subject_article WHERE subject_id = s.id) AS article_num
FROM crm_subject s
ORDER BY article_num DESC;
获得结果如下:

这个 SQL 语句,查询出了项目产品所对应的文章数,下面基于它再做个优化调整,把查询到的文章数量 article_num 变为提交文章的用户数量 member_num。
再优化一下,意外发生了
现在不是直接从文章表中,获取文章数量了,而是需要先根据文章表中的用户ID进行分组,获得分组数据之后,再通过 count(*) 聚合函数,拿到用户数量。于是继续调整 SQL 如下:
SELECT s.id, s.name, (SELECT count(*) FROM (SELECT mg_userid FROM art_subject_article WHERE subject_id = s.id GROUP BY mg_userid) t) AS member_num
FROM crm_subject s
ORDER BY member_num DESC;
但是,运行却报错了:
报错信息说:s.id 字段找不到。这是一个嵌套的子查询,在嵌套的最内层的子查询中,关联外部表的字段,是无法关联的。虽然我没找根据,但通过报错信息,也能大致看出一二。而且,在 DataGrip 中,把鼠标放到 s.id 上面时,也会出现一个提示:

虽然这个提示,我也不甚明了,但是感觉上,好像就是在告诉我,你无法关联到外部表的字段。
好像无解了,转变思路,柳暗花明
上面的 SQL 语句,看起来是如此的完美,可是就是有问题、不成立,咋办?
突然,灵机一动,想到一个方案,姑且一试。既然在嵌套的最内层的子查询中,做 WHERE subject_id = s.id 与主表的字段关联行不通,那么,就不在内层的子查询中做关联,把它提到外层的子查询中去,不就行的通了嘛。于是,改造 SQL 如下:
SELECT s.id, s.name, (SELECT count(*) FROM (SELECT subject_id, mg_userid FROM art_subject_article GROUP BY subject_id, mg_userid) t WHERE t.subject_id = s.id) AS member_num
FROM crm_subject s
ORDER BY member_num DESC;
主要关注子查询这里的改造,我们可以把这里的子查询做个分解。
首先,可以把子查询看成这样:(SELECT count(*) FROM t WHERE t.subject_id = s.id) AS member_num,把它理解成从 t 表中查询与主表的项目产品有关的记录数量。
然后,我们再把 t 表看成 (SELECT subject_id, mg_userid FROM art_subject_article GROUP BY subject_id, mg_userid) t,代表从文章表中查询出每个产品对应的用户ID。
最后把2个子查询,整合起来,就实现了查询项目产品表中,每个产品所对应的提交了文章的用户数量。
有没有更好的解决方案
这个折中的方案,虽然可以解决我的问题,但是,我依然想知道,有没有更好的、更标准的最佳实践。
并且此方案,也有3点不足:
改进前我们是对文章表做项目产品关联查询后再分组,改进后是对文章表做全表扫描后的分组,效率较低,在大数据下的表现不好。
优化方案是基于两层嵌套的子查询进行的,假如需要三层嵌套的子查询,此方案估计又失效了。
此优化方案较为局限,不具有普适性,不能很好的适用于各种业务场景。
所以,我将我遇到的这个问题,和解决方案分享在此,希望能帮助到有缘人,同时,也期望各位大神能够不吝赐教,分享一下最佳实践。
关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法的更多相关文章
- Mysql in子查询中加limit报错
Mysql in子查询中加limit报错 select id from aa where id in ( select id from bb limit 10 ); 改写成 SELECT id FRO ...
- mysql更新子查询中的内容
UPDATE t_finance_certify_copy c SET c.biz_type=2,c.sub_biz_type=18WHERE c.finance_certify_id IN(SELE ...
- laravel 迁移文件中修改含有enum字段的表报错解决方法
解决方法: 在迁移文件中up方法最上方加上下面这一行代码即可: Schema::getConnection()->getDoctrineSchemaManager()->getDataba ...
- Mysql Join-连接查询(中)
Mysql Join-连接查询(中) 认识 就我平时的数据接触来看, 连接查询也没有很复杂,不够是非常需要耐心和逻辑的, 一点点将数据查出来, 拼接等. 没有什么技巧, 多练习就会了. 无非就是表之间 ...
- mysql in 子查询 效率慢 优化(转)
mysql in 子查询 效率慢 优化(转) 现在的CMS系统.博客系统.BBS等都喜欢使用标签tag作交叉链接,因此我也尝鲜用了下.但用了后发现我想查询某个tag的文章列表时速度很慢,达到5秒之久! ...
- MySQL 行子查询(转)
MySQL 行子查询 行子查询是指子查询返回的结果集是一行 N 列,该子查询的结果通常是对表的某行数据进行查询而返回的结果集. 一个行子查询的例子如下: SELECT * FROM table1 WH ...
- MySQL FROM 子查询
FROM 子句中的子查询 MySQL FROM 子查询是指 FROM 的子句作为子查询语句,主查询再到子查询结果中获取需要的数据.FROM 子查询语法如下: SELECT ... FROM (subq ...
- SQL相关子查询是什么?和嵌套子查询有什么区别?
目录 两者的各种叫法 相关子查询MySQL解释 相关子查询Wikipedia解释 相关子查询执行步骤拆解 相关子查询和嵌套查询的区别 参考资料 两者的各种叫法 相关子查询叫做:Correlated S ...
- Mybatis 一对多延迟加载,并且子查询中与主表字段不对应 (19)
Mybatis 一对多延迟加载,并且子查询中与主表字段不对应应用说明. 实现一对多关联(懒加载),一个教研组对应多个教师,既:教师的教研编号与教研组的教研编号关联,并且教师关联教研组外键与教研组编号 ...
- [SQL SERVER系列]之嵌套子查询和相关子查询
子查询有两种类型,一种是只返回一个单值的子查询,这时它可以用在一个单值可以使用的地方,这时子查询可以看作是一个拥有返回值的函数:另外一种是返回一列值的子查询,这时子查询可以看作是一个在内存中临时存在的 ...
随机推荐
- docker搭建yapi接口文档系统、Idea中上传接口、在线调用
一.前言 在我们后端开发中,必不可少的是接口的交接,有很多种方式,常见的就是swagger,不过这个侵入性太强了.还有就是接口文档的框架,比如今天小编带大家一起搭建的yapi,在公司还是挺常见的! 今 ...
- HDU2196 Computer (树形DP-换根)
dp[u][0]表示u向下走的最大距离: dp[u][1]表示u向下走的次大距离: dp[u][2]表示u向上走的最大距离: 最后的答案就是每个点的max(dp[u][0],dp[u][2]); 求解 ...
- 最近无聊搭建一个齐博X1的下载页面
https://layui.wanxiangsucai.com/ 用layui官方镜像站的模版 改了个齐博X1的下载页面 https://x1.wanxiangsucai.com/ 哈哈哈!!! 还有 ...
- 1、在SrpingBoot的环境当中使用JSP及相关功能
创建webapp目录 由于SpringBoot项目不建议直接访问jsp页面,但是我现在要做的事情需要去访问,那么我就需要在原有的项目基础上为访问jsp页面进行一个调整 首先在项目当中,java和res ...
- Linux执行jsp命令的时候报错:-bash: jps: command not found
前言:在zookeeper学习的时候,执行jsp命令查看zookpper运行状态的时候发现报错: -bash: jps: command not found 翻阅了一大批文章,不是东拼西凑,就是缺斤少 ...
- ES集群检查常用命令
一.集群检查常用命令 查询集群状态命令: curl -XGET "http://ip:port/_cluster/health?pretty" 查询Es全局状态: curl -XG ...
- C. 连锁商店(状压dp)
C. 连锁商店 time limit per test 1 second memory limit per test 512 megabytes input standard input output ...
- go:快速添加接口方法及其实现
问题描述 在大型项目中,通常存在多个模块,模块对外暴露的功能通常是通过接口封装,这样可以明确模块的功能,有效降低模块与模块之间的耦合度,同时模块与模块之间进行合理的组装.接口的实现,有时可能存在多个实 ...
- Archlinux + Dwm 配置流程
本着学习C的态度来了解dwm,本身作为一个i3wm的追崇者,与dwm会擦出怎么样的火花呢? 下载安装dwm archlinuxcn源配置 编辑/etc/pacman.conf文件,添加bfsu的arc ...
- ubuntu20.04修改静态ip不生效问题
一.前言 最近从头开始配置hadoop的时候,由于想切换到NAT模式下配置hadoop,但在修改ip的时候发现设置了静态ip,但ip不生效,查了很多资料,发现由于配置信息写错了. 二.解决问题 ifc ...