首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MYSQL多表联合查询

MYSQL多表联合查询

作者头像
雪碧君
发布于 2023-02-15 06:50:13
发布于 2023-02-15 06:50:13
3.1K00
代码可运行
举报
运行总次数:0
代码可运行

在一个大型的复杂应用中,我们通常会将不同模块的数据存储到各自的表中 例如在APPsite框架中我们默认了4张用户表 分别存储了 user_account 账户表 user_info 详情表 user_pocket 钱包表 user_group 分组表

这样我们在读写数据的时候可以做到表级别的隔离,防止一些api 或是 内外部方法导致的数据泄露问题,提高安全性和事务方法的紧密度。 当然也有一定的减轻单张表结构过于臃肿的作用。

这里的表拆分,要基于业务划分去做,譬如说详情、分组、钱包在用户的鉴权、登录包括收发消息等行为时都不需要,那么我们就可以将这些部分的数据转移到新的表中。保持account表的高效性。

于此对应的是我们在进行后台的丰富数据查询时就需要合并表进行查询,今天特意整理一下使用JOIN进行多表联合查询的注意点。

首先是最简单的范例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JOIN查询 双表
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid

在多表查询时,我们会遇到某个表 对应项目为空时的情况, 这时根据JOIN方式就会有不同的结果。其中INNER 方式就会取交集合并结果,而LEFT方式左表会完整展示,右表不满足条件的数据会被剔除为空。

看三个对比:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JOIN 多表条件查询
# 靠后的表会是左右的反方向追加进来

# case1
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_group ON user_account.groupid = user_group.groupid AND user_group.level > 100
# 取出了所有用户数据、 其中用户level不大于100用户组信息被抹掉(NULL)

# case2
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
INNER JOIN user_pocket ON user_account.userid = user_pocket.userid AND user_pocket.point > 5000
LEFT JOIN user_group ON user_account.groupid = user_group.groupid
# 仅取出所有积分大于5000的用户数据

# case3
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid AND user_pocket.point > 5000
INNER JOIN user_group ON user_account.groupid = user_group.groupid AND  user_group.level > 100 
# 取出了所有用户level大于100的用户数据,且其中积分不大于5000的用户钱包信息被抹掉(NULL)

在这个部分我们可以通过INNER有效的控制最终的结果数量,譬如说在进行筛选查询时。 而我们要进行范围查询,其中可能包含空值的时候,就应该用LEFT,RIGHT 而左右决定了哪一边是全表,另外一边来补齐的策略。

另外一个比较重要的是,WHERE条件 和 JOIN表内条件的作用范围,同样上一个范例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JOIN 表内AND条件 与 WHERE条件的作用范围

# case1
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_group ON user_account.groupid = user_group.groupid
WHERE user_group.level > 100
# 仅取出了用户level不大于100的

# case2
SELECT * FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid 
LEFT JOIN user_group ON user_account.groupid = user_group.groupid AND user_group.level > 100
WHERE user_pocket.point > 5000
# 仅取出所有积分大于5000的用户数据,同时 用户级别不大于100的用户组信息被抹掉(NULL)

这里可以归纳一个简单的策略:

JOIN语句手拉手 一键查询数据有 屏蔽数据表内AND 过滤筛选WHERE最后

虽然我们可以用INNER+表内条件的方式来进行筛选,但是这里推荐的是 如果要筛选就全部写在WHERE语句中,这样在查询的时候MYSQL会优化查询减少整体的运算量。

在使用JOIN查询的时候我们还会有统计行数的需求,为了减少MYSQL服务器的计算量,其实这里我们也可以做一些优化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JOINCOUNT查询效率优化

# case1
SELECT COUNT(*) FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid 
LEFT JOIN user_group ON user_account.groupid = user_group.groupid AND user_group.level > 100
WHERE user_pocket.point > 5000

在上面的case中,我们可以分析出 user_info 因为没有筛选条件、所以一定不会影响最终结果,所以这一行可以省略。 user_group因为只是一个表内筛选,也不会影响最终行数 所以也可以省略。 接下来是user_pocket,这一条件决定了最终结果的呈现,所以不能省略。那么可以优化成:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# case1.1
SELECT COUNT(*) FROM user_account 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid 
WHERE user_pocket.point > 5000

这里我们会发现,如果在user_account表中也没有筛选条件的话,那其实我们仅仅需要统计user_pocket表内的行数即可( 这里存在疑问是 user_account.userid 是否可以和 user_info.userid能做到一一对应 )。 我们可以继续优化成一句单表查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# case1.2
SELECT COUNT(*) FROM user_pocket WHERE user_pocket.point > 5000

在优化COUNT的时候,另一种情况就是 一张或多张表 都存在有效筛选的情况。这个时候我们不可避免的还是要使用联合查询。 可以优化的就是将不参与筛选的表从中移除,这样以便于优化查询效率。 如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JOINCOUNT查询效率优化 多个有效筛选字段

# case 2
SELECT COUNT(*) FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid 
LEFT JOIN user_group ON user_account.groupid = user_group.groupid AND user_group.level > 100
WHERE user_info.wechatid IS NOT NULL AND user_pocket.point > 5000

# 由于 user_info , user_pocket 都有有效筛选条件 所以我们可以优化为

# case 2.1
SELECT COUNT(*) FROM user_account 
LEFT JOIN user_info ON user_account.userid = user_info.userid 
LEFT JOIN user_pocket ON user_account.userid = user_pocket.userid 
WHERE user_info.wechatid IS NOT NULL AND user_pocket.point > 5000

# 如果考虑到我们已经做到完美对应 可以将 主表进一步优化掉

# case 2.2
SELECT COUNT(*) FROM user_info
LEFT JOIN user_pocket ON user_info.userid = user_pocket.userid 
WHERE user_info.wechatid IS NOT NULL AND user_pocket.point > 5000

在最后一步优化时,我们看是将最靠左的一个有效筛选表替换为主表,同时关联的表名也进行调整。 在效率要求不高的情况下,我个人还是建议采用2.1的方式。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL千万大表优化实践
前段时间笔者遇到一个复杂的慢查询,今天有空便进行了整理,以便日后回顾。举一个相似的业务场景的例子。以文章评论为例,查询20191201~20191231日期间发表的经济科技类别的文章,同时需要显示这些文章的热评数目
王知无-import_bigdata
2020/09/25
2.1K0
MySQL千万大表优化实践
MySQL 调试篇
本篇主讲如何使用 explain 和 explain 各个参数的意义、如何查看被优化器优化后的 SQL 和手动影响优化器的优化。
啵啵肠
2023/11/20
3460
Mysql - JOIN 详解
一个完整的SQL语句中会被拆分成多个子句,子句的执行过程中会产生虚拟表(vt),但是结果只返回最后一张虚拟表。从这个思路出发,我们试着理解一下JOIN查询的执行过程并解答一些常见的问题。
前端教程
2018/07/27
5K0
MySQL的多表联合查询
MySQL多表联合查询包括内连接、外连接、笛卡尔积连接查询三种。今天我们通过实验来演示7种SQL JOINS的基本用法。
Power
2025/02/28
4960
作为开发也要了解的 mysql 优化思路
为了更好的说明,我假想出来了一个业务场景,可能在实际业务中并不存在这样的场景,只为举例说明问题:
古时的风筝
2018/05/09
9270
MYSQL多表查询与事务
select * from emp,dept where emp.`dept_id` = dept.`id`;#设置过滤条件(隐式内连接)
嘘、小点声
2019/09/29
1K0
MYSQL多表查询与事务
牛客-SQL练习
题目地址:查找学校是北大的学生信息_牛客题霸_牛客网 (nowcoder.com)
小简
2023/01/04
2.5K0
MySQL分组统计与多表联合查询的基本知识归纳总结
having 对分组后的数据进行条件筛选,与where相似,但是只针对分组后的数据,where无法筛选聚合函数
Java帮帮
2018/12/21
5K0
MySQL分组统计与多表联合查询的基本知识归纳总结
关于MySQL多表联合查询,你真的会用吗?
上节课给大家介绍了MySQL子查询的基本内容,具体可回顾MySQL子查询的基本使用方法(四),本节课我们准备给大家介绍MySQL的多表联合查询。大家都知道,MySQL多表联合查询包括内连接、外连接、笛卡尔积连接查询三种。今天我们先重点介绍常用的外连接与内连接查询,即left join /right join/inner join的基本用法。
用户7569543
2021/11/02
9.9K0
MySQL多表联合查询
例 2:查询 tb_course 表中的 id 字段和 tb_students_info 表中的 course_id 字段相等的内容
Alone-林
2022/08/20
11.1K0
9.MySQL高阶查询方法——聚合查询 / 联合(多表)查询
多表查询的过程就是先计算两张表的笛卡尔积,再根据一些条件对笛卡尔积中的记录进行筛选
小雨的分享社区
2022/10/26
1.9K0
9.MySQL高阶查询方法——聚合查询 / 联合(多表)查询
盘点MySQL慢查询的12个原因
日常开发中,我们经常会遇到数据库慢查询。那么导致数据慢查询都有哪些常见的原因呢?今天田螺哥就跟大家聊聊导致MySQL慢查询的12个常见原因,以及对应的解决方法。
捡田螺的小男孩
2023/02/24
1.7K0
盘点MySQL慢查询的12个原因
Mysql 多表联合查询效率分析及优化
1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用',' 如:
黄规速
2022/04/14
3.9K0
hive基本使用
由于最近项目需要和大数据对接,需要了解一下数仓的基本知识,所以记录一下hive的基础原理和使用
leobhao
2022/06/28
9490
hive基本使用
数据库基础,看完这篇就够了!
对于测试同学来说,除了知道测试基础知识外,还需要掌握一些测试基本技能,主要有Linux、数据库、计算机网络等,在此之前我们已经讨论过Linux基础知识以及在实际工作中的应用,可参考往期文章「学会Linux,看完这篇就行了!」。
测试蔡坨坨
2022/12/21
3.3K0
数据库基础,看完这篇就够了!
MyBatis 多表联合查询及优化
这篇文章我打算来简单的谈谈 mybatis 的多表联合查询。起初是觉得挺简单的,没必要拿出来写,毕竟 mybatis 这东西现在是个开发的都会用,而且网上的文章也是一搜罗一大堆,根本就用不着我来重复。但是吧,就我前几天在做一个多表联合查询的时候,竟然出了很多意想不到的问题,而且这些问题的出现,并不是对 mybatis 不了解,而是在用的过程中会或多或少的忽略一些东西,导致提示各种错误。
全栈程序员站长
2022/08/12
1.2K0
MyBatis 多表联合查询及优化
12个MySQL慢查询的原因分析「建议收藏」
很多时候,我们的慢查询,都是因为没有加索引。如果没有加索引的话,会导致全表扫描的。因此,应考虑在 where 的条件列,建立索引,尽量避免全表扫描。
全栈程序员站长
2022/11/04
2.4K0
MySQL秘籍之索引与查询优化实战指南
最左前缀原则。不冗余原则。最大选择性原则。所谓前缀索引,说白了就是对文本的前几个字符建立索引(具体是几个字符在建立索引时去指定),比如以产品名称的前 10 位来建索引,这样建立起来的索引更小,查询效率更快!
千寻简
2025/01/03
4510
MySQL秘籍之索引与查询优化实战指南
MYSQL回顾(多表查询相关)
简单的数据我们可以直接从一个表中获取,但在真实的项目中查询符合条件的数据通常需要牵扯到多张表,这就不得不使用多表查询。多表查询分为多表连接查询、符合条件链接查询、子查询。多表连接查询包括内连接、外连接、全连接。符合条件连接查询本质上是多表连接查询+过滤条件。子查询是将一个查询语句嵌套在另一个查询语句中,内层查询语句的查询结果作为外层查询语句的数据源。
VV木公子
2020/02/18
5.5K0
sql多表联合查询详解_sql多表查询例子
这条语句 其中 select,as, count ,from where,in ,and,group up都是关键字,这条语句的意思是:bi_BillItem根据billid去bill表查满足这些条件的如果查到满足条件billid相等的就查询出bi_BillItem中的menuId,menuName,MenuPrice,(sum(AmountOrder)-sum(AmountCancel))字段 并且按 menuId和menuPrice排序
全栈程序员站长
2022/09/22
2.9K0
相关推荐
MySQL千万大表优化实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验