当前位置: 首页 > news >正文

三个表联合查询的场景分析-场景1:a表关联了b表和c表

本场景对应情景如下:

三个数据表,一个表的两个字段分别关联了另外两个表各自的id数据,可能包含多个id(两个1对多关联)。

目录

数据表准备

需求1、查询c表的列表数据,要求获得关联的b表中的name(多个)

需求2、在需求1基础上,同时查询关联的a表的name(多个)

需求3、在需求2基础上,增加整体聚合结果按“创建时间”排序、分页


数据表准备

共三张表,a、b、c,c表中关联了a和b的id

demo_bs表

ae822a1d5b33478cb4ad0cb5313eae50.png

demo_as表

f95b2267035949209fa34ea660ccad3a.png

demo_cs表

94cdf3ea6629474e988878aaf548c287.png

a_ids:关联的a表的id列表,使用英文逗号分隔;可不关联a,不关联时为空字符串;

b_ids:关联的b表的id列表,使用英文逗号分隔;必定关联了b中的某些id,至少关联了1个;

需求1、查询c表的列表数据,要求获得关联的b表中的name(多个)

         select c.id AS id,c.name AS name,c.created_at AS createdAt,

         c.b_ids as bIDs, c.a_ids as aIDs, group_concat(b.name SEPARATOR ',')  as bNames

         from demo_cs  c

         left join demo_bs  b

         on FIND_IN_SET(b.id, c.b_ids) > 0

         where c.name like '%c%'

         group by c.id

查询结果

b30c61afa3234824a9860ad3ae7cb19b.png

其中where c.name like '%c%'为c表本表的name字段查询条件。

FIND_IN_SET(b.id, c.b_ids) > 0表示检查b.id值在c.b_ids中的索引(且后者是以逗号拼接的字符串),索引从1开始,因此判断结果只要>0则表示前者在后者中存在。

group_concat(b.name SEPARATOR ',')表示将b表的name字段以逗号拼接作为新的一列,那么是b表的哪些name呢?即符合on FIND_IN_SET(b.id, c.b_ids) > 0 条件的记录的name。

需求2、在需求1基础上,同时查询关联的a表的name(多个)

select r.id,r.name,r.createdAt,r.bIDs as bIDs,r.bNames as bNames,r.aIDs as aIDs,group_concat(a.name SEPARATOR ',') as aNames

from(

         select c.id AS id,c.name AS name,c.created_at AS createdAt,

         c.b_ids as bIDs, c.a_ids as aIDs, group_concat(b.name SEPARATOR ',')  as bNames

         from demo_cs  c

         left join demo_bs  b

         on FIND_IN_SET(b.id, c.b_ids) > 0

         where c.name like '%c%'

         group by c.id

) r

left join demo_as a

on FIND_IN_SET(a.id, r.aIDs) > 0

where  r.bNames like '%b%'

group by r.id

查询结果

ae5a3a1db82d4da2baad1d92c502c8ca.png

其中where  r.bNames like '%b%'为聚合后数据的b的名称列表的查询条件。此时用于在内部查询基础上如

b5_hello,bb3,b2

中(即bNames)判断是否包含b。如果将此条件放在子查询内部:如

where  b.name like '%b%'

会导致数据不准确,b.name like查询的是仅b表的name字段的模糊查询,可能会导致子查询查出的数据量减少,注意查询条件的定位,不同位置含义不同。

因为查询的主表是c表,因此from内部的子查询为数据基本盘,from内部的子查询的数据准确则整体数据准确。

需求3、在需求2基础上,增加整体聚合结果按“创建时间”排序、分页

select r.id,r.name,r.createdAt,r.bIDs as bIDs,r.bNames as bNames,r.aIDs as aIDs,group_concat(a.name SEPARATOR ',') as aNames

from(

         select c.id AS id,c.name AS name,c.created_at AS createdAt,

         c.b_ids as bIDs, c.a_ids as aIDs, group_concat(b.name SEPARATOR ',')  as bNames

         from demo_cs  c

         left join demo_bs  b

         on FIND_IN_SET(b.id, c.b_ids) > 0

         where c.name like '%c%'

         group by c.id

) r

left join demo_as a

on FIND_IN_SET(a.id, r.aIDs) > 0

where  r.bNames like '%b%'

group by r.id

order by r.createdAt desc

limit 10 offset 0

查询结果

1e42b34cebff4cf28af7aa37cb555b0c.png

注意,外层的on FIND_IN_SET(a.id, r.aIDs) > 0 条件是作用在a表和查询出来的r结果之上因此aIDs即使为空字符串,也不会导致最终结果的数量减少,而是对应的aNames查出来为空而已(aIDs没有id,对应的aNames为空正常)。

如果需要第二页,则将最后面的limit 10 offset 0 换为 limit 10 offset 10即可。

相关文章:

  • 【Java基础】IO流(二)字符集知识
  • vue3路由跳转时,页面如何滚动到顶部
  • 如何更改ldap用户在local node上的默认shell
  • 从前端到前端框架
  • 专题二 - 滑动窗口 - leetcode 76. 最小覆盖子串 | 困难难度
  • Node.js入门基础—day01
  • Notepad++从文件夹查找文本内容
  • Vue2 + node.js项目
  • Apache Paimon 的 CDC Ingestion 概述
  • linux 安装gradle7.4.2环境
  • apache commons-dbcp Apache Commons DBCP 软件实现数据库连接池 commons-dbcp2
  • chatGPT的耳朵!OpenAI的开源语音识别AI:Whisper !
  • spring 面试题
  • 第三章 OpenGL ES 基础-基础-GLSL渲染纹理
  • 安卓通过termux部署ChatGLM
  • github(不是git啊)操作记录(踩坑)
  • Linux 自动检测进程是否存活,如果挂掉自动拉起
  • Nodejs 第五十四章(net)
  • linux常用命令2
  • C语言游戏实战(4):人生重开模拟器
  • 《三餐四季》广东篇今晚开播:食在岭南,遇见百味
  • 美国长滩港货运量因关税暴跌三成,港口负责人:货架要空了
  • 观察|天空之外的战场:官方叙事、新闻与社交平台中的印巴冲突
  • 国际足联女子世界杯再次扩军,2031年起增至48支球队
  • 中非民间对话在赞比亚举行
  • 央行:货币与物价的关系受多重因素影响,提振物价的关键在于扩大有效需求