首页 > 数据库 >关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法

关于 MySQL 嵌套子查询中,无法关联主表字段问题的折中解决方法

时间:2022-12-24 14:56:14浏览次数:52  
标签:折中 文章 查询 嵌套 num MySQL id SELECT subject

今天在工作中写项目的时候,遇到了一个让我感到几乎无解的问题,在转换了思路后,想出了一个折中的解决方案,记录如下。

其实,问题的场景,非常简单:

就是需要查询出上图的数据,红框是从 项目产品表 中查询的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点不足:

  1. 改进前我们是对文章表做项目产品关联查询后再分组,改进后是对文章表做全表扫描后的分组,效率较低,在大数据下的表现不好。

  2. 优化方案是基于两层嵌套的子查询进行的,假如需要三层嵌套的子查询,此方案估计又失效了。

  3. 此优化方案较为局限,不具有普适性,不能很好的适用于各种业务场景。

所以,我将我遇到的这个问题,和解决方案分享在此,希望能帮助到有缘人,同时,也期望各位大神能够不吝赐教,分享一下最佳实践。

标签:折中,文章,查询,嵌套,num,MySQL,id,SELECT,subject
From: https://www.cnblogs.com/bananaplan/p/mysql-cannot-find-outer-table-column-in-nested-subque

相关文章

  • MySQL
    第1章今日内容1.MySQLMySQL:是用于管理文件的一个软件服务端软件socket服务端本地文件操作解析指令(SQL语句)客户端软件(各种各样)socket客户端发......
  • 解决MySQL5.5MySQLInstanceConfig最后一步setting报错
    问题描述在安装过MySQL(或已卸载)的电脑中重新安装MySQL5.5, 在安装最后一项中Processing configuration中最后一项配置失败:问题解决:首先关于卸载:安装时候若使......
  • 深入理解 MySQL 索引底层原理
      一步一步推导出Mysql索引的底层数据结构。Mysql作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是Mysql数据的存储形式以......
  • 深入理解 MySQL 索引底层原理
      一步一步推导出Mysql索引的底层数据结构。Mysql作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是Mysql数据的存储形式以......
  • 深入理解 MySQL 索引底层原理
      一步一步推导出Mysql索引的底层数据结构。Mysql作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是Mysql数据的存储形式以......
  • mysql查询 limit 1000,10 和limit 10 速度一样快吗?如果我要分页,我该怎么办?
    刷网站的时候,我们经常会遇到需要分页查询的场景。比如下图红框里的翻页功能。我们很容易能联想到可以用mysql实现。假设我们的建表sql是这样的建表sql大家也不用扣细节,只需......
  • 详解MySQL事务(transaction),用图直观解释了MySQL脏读、不可重复读、幻读的问题
    事务事务是一组操作的集合,会把所有操作作为一个整体去执行,要么同时成功,要么同时失败。事务操作查看/设置事务提交方式SELECT@@autocommit;#1为自动,0为手动SET@@......
  • 初识MySQL(四)单表select查询操作
    数据准备:用户表user:createtableuser(idintunsignedprimarykeynotnullauto_increment,namevarchar(50)UNIQUEnotnull,agetinyintnotnull,......
  • T1408 矩阵嵌套(DAG 记忆化搜索)
    T1408矩阵嵌套​ 有n个矩阵,每个矩阵有长x和宽y。我们定义矩阵A可以嵌套在矩阵B中:A.x>B.x且A.y>B.y或者A.x>B.y且A.y>B.x。我们现在要找一个最长......
  • win10系统安装mysql
    1.下载mysql在这个网址:downloads.mysql.com/archives/community/(前面需要加HTTPS),找到Windows(x86,64-bit),ZIPArchive这一行,然后下载解压到D:\MYSQL;2.配置mysq......