基础SQL演练,带详细分析,笔记和备忘。
行文不易,感谢支持!
本场景对应概况如下:
三个数据表,一个表的字段关联了第二张表的id(1对1关联),第二个表的某字段关联了第三个表的id,可能包含多个id(1对多关联)。
相关好文:
三个表联合查询的场景分析-场景2:a表关联b表、b表关联c表
三个表联合查询的场景分析-场景3:c表维护a和b表的id关联关系(id间1对1)
三个表联合查询的场景分析-场景4:c表维护a和b表的id关联关系(id间一对多)
单表复杂查询的场景分析一:涉及数据分组/函数计算/日期处理/SQL变种
单表复杂查询的场景分析二:涉及数据分组与分区/多重函数计算/SQL变种
目录
需求1:查询f表的列表数据,包括每条记录对应的eID值,及其该eID关联的d表的id值
需求2:在需求1基础上继续查询eid关联的每条d表中的name,同时每条记录的多个d的name字段拼接在一起
数据表
共三张表,d、e、f。f中关联了e的id,e中关联了d的id。
d表(demo_ds)
e表(demo_es)
f表(demo_fs)
需求1:查询f表的列表数据,包括每条记录对应的eID值,及其该eID关联的d表的id值
select f.id AS id,f.name AS name,f.created_at AS createdAt,
f.eid as eID, e.d_ids as dIDs
from demo_fs f
left join demo_es e on e.id=f.eid
left join demo_ds d on FIND_IN_SET(d.id, e.d_ids) > 0
where e.name like '%e%' and f.name like '%f%'
group by f.id
查询结果
需求2:在需求1基础上继续查询eid关联的每条d表中的name,同时每条记录的多个d的name字段拼接在一起
select f.id AS id,f.name AS name,f.created_at AS createdAt,
f.eid as eID, e.d_ids as dIDs, group_concat(d.name SEPARATOR ',') as dNames
from demo_fs f
left join demo_es e on e.id=f.eid
left join demo_ds d on FIND_IN_SET(d.id, e.d_ids) > 0
where f.name like '%f%'
group by f.id
查询结果
通俗的翻译一下:获得了f表中的每条记录,以及每条记录关联的e表中的数据,以及上述数据中e表中关联了d表的id,同时获得这些id对应的名称,即一条f记录可以找到关联的多个d表的记录。
需求3:需求2基础上修改数据
我们将f表中id为6的记录对应的eid修改成7(本身为6),也就是说修改的id在e表中不存在。此时继续使用需求2中的SQL查询,结果如下:
此时如果我们把JOIN e表的部分使用内连接,
select f.id AS id,f.name AS name,f.created_at AS createdAt,
f.eid as eID, e.d_ids as dIDs, group_concat(d.name SEPARATOR ',') as dNames
from demo_fs f
inner join demo_es e on e.id=f.eid
inner join demo_ds d on FIND_IN_SET(d.id, e.d_ids) > 0
where f.name like '%f%'
group by f.id
查询结果:
结果中不会包含f表id=6的记录,因为此时 inner join demo_es e on e.id=f.eid聚合出来的临时表计算的是e表和f表的交集,即仅满足e.id=f.eid 即可。
而第二个JOIN中inner join demo_ds d是连接d表,相当于找出符合e.d_ids条件的d中的数据,这可以理解为仅是影响设置每条查出来的记录上的dIDs字段,即e和d之间连接并不能决定最终查询出来的结果数量,因此这里是否改为inner不影响结果。