从多表连接后的select count(*)看待SQL优化
从多表连接后的select count(*)看待SQL优化
一朋友问我,以下这SQL能直接改写成select count(*) from a吗?
SELECT COUNT(*)
FROM a
LEFT JOIN b ON a.a1 = b.b1
LEFT JOIN c ON b.b1 = c.c1
废话不多说,直接上实验。
1. 准备数据
创建测试表a,b,c,并插入数据,a有重复数据,b是唯一数据,c是唯一数据,d有重复数据。
1) 创建a表
create table a (a1 int);
insert into a select 1;
insert into a select 2;
insert into a select 3;
insert into a select 1;
insert into a select 2;
insert into a select 3;
insert into a values(null);
insert into a values(null);
insert into a values(null);
insert into a values(null);
2)创建b表
create table b (b1 int);
insert into b select 1;
insert into b select 2;
insert into b select 3;
insert into b select 4;
insert into b select 5;
3)创建c表
create table c (c1 int);
insert into c select 7;
insert into c select 8;
insert into c select 9;
insert into c values(null);
insert into c values(null);
4)创建d表
create table d (d1 int);
insert into d select 1;
insert into d select 1;
insert into d select 1;
insert into d select 1;
insert into d select 1;
insert into d select 1;
2. 数据查看
| a表 | b表 | c表 | d表 |
|---|---|---|---|
| 1 | 1 | 7 | 1 |
| 2 | 2 | 8 | 1 |
| 3 | 3 | 9 | 1 |
| 1 | 4 | null | 1 |
| 2 | 5 | null | 1 |
| 3 | 1 | ||
| null | |||
| null | |||
| null | |||
| null |
3. SQL示例
3.1 a表连接b表再连接c表(N:1:1的关系)
a表连接列有重复数据,b,c两表的连接列都是唯一数据
SELECT COUNT(*)
FROM a
LEFT JOIN b ON a.a1 = b.b1
LEFT JOIN c ON b.b1 = c.c1 +----------+
| COUNT(*) |
+----------+
| 10 |
+----------+
1 row in set (0.00 sec)
返回的10条数据
此时SQL只返回a表的数据,那么这时候SQL可以改写成
mysql> select count(*) from a;
+----------+
| count(*) |
+----------+
| 10 |
+----------+
1 row in set (0.00 sec)
3.2 b表连接a表再连接c表(1:N:1的关系)
SELECT count(*)
FROM b
LEFT JOIN a ON b.b1 = a.a1
LEFT JOIN c ON a.a1 = c.c1 +----------+
| count(*) |
+----------+
| 8 |
+----------+
1 row in set (0.00 sec)
原本b表是5条数据,left join后变为8条,此时就不能改写成上述形式了,我们来看下,具体数据是什么。
+------+------+------+
| b1 | a1 | c1 |
+------+------+------+
| 1 | 1 | NULL |
| 2 | 2 | NULL |
| 3 | 3 | NULL |
| 1 | 1 | NULL |
| 2 | 2 | NULL |
| 3 | 3 | NULL |
| 4 | NULL | NULL |
| 5 | NULL | NULL |
+------+------+------+
8 rows in set (0.00 sec)
可以看到a表的重复数据,在b表重复展现了,c表与a表连接,没有相等的数据(null不等于null)所以c1列展现都为null值。
这时候此SQL可以等价于以下:
SELECT count(*)
FROM b
LEFT JOIN a ON b.b1 = a.a1; +----------+
| count(*) |
+----------+
| 8 |
+----------+
1 row in set (0.00 sec)
3.3 a表与d表相连接(N:N关系)
SELECT *
FROM a
LEFT JOIN d ON a.a1 =d.d1; +------+------+
| a1 | d1 |
+------+------+
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 2 | NULL |
| 3 | NULL |
| 2 | NULL |
| 3 | NULL |
| NULL | NULL |
| NULL | NULL |
| NULL | NULL |
| NULL | NULL |
+------+------+
20 rows in set (0.00 sec)
可以看a表a1列数据组成是 a表2个1 * b表 6个1 = 12个1,再加上原本a1列的数据8条,总共20条数据。
4. 总结
从以上实验可以延伸到,如果连接列基数很低,此时left join就相当于笛卡儿积。。
所以在做SQL优化时候,尤其需要关注连接列的基数,与表与表之间的关系。
从多表连接后的select count(*)看待SQL优化的更多相关文章
- 数据库多表连接方式介绍-HASH-JOIN
1.概述 hash join是一种数据库在进行多表连接时的处理算法,对于多表连接还有两种比较常用的方式:sort merge-join 和 nested loop. 为了比较清楚的介绍hash joi ...
- Oracle多表连接,提高效率,性能优化 (转)
执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要几十表了. ...
- PostgreSQL EXPLAIN执行计划学习--多表连接几种Join方式比较
转了一部分.稍后再修改. 三种多表Join的算法: 一. NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表 ...
- Oracle多表连接效率,性能优化
Oracle多表连接,提高效率,性能优化 (转) 执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只 ...
- SqlServer 多表连接、聚合函数、模糊查询、分组查询应用总结(回归基础)
--exists 结合 if else 以及 where 条件来使用判断是否有数据满足条件 select * from Class where Name like '%[1-3]班' if (not ...
- Access数据库多表连接查询
第一次在Access中写多表查询,就按照MS数据库中的写法,结果报语法错,原来Access的多表连接查询是不一样的 表A.B.C,A关联B,B关联C,均用ID键关联 一般写法:select * fro ...
- SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好?
SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好? 今天遇到某人在我以前写的一篇文章里问到 如果统计信息没来得及更新的话,那岂不是统计出来的数据时错误的 ...
- Oracle表连接
一个普通的语句select * from t1, t2 where t1.id = t2.id and t1.name = 'a'; 这个语句在什么情况下最高效? 表连接分类: 1. 嵌套循环连接(N ...
- select count(*)和select count(1)的区别 (转)
A 一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的 假如表沒有主键(Primary key), 那么count(1)比count(*)快, 如果有主键 ...
随机推荐
- 11.5NOIP模拟赛
/* 唉,那个第二种策略应该是没用吧. 为什么我列出式子最优策略跟第二种策略有关??为什么我写了写分布列还是跟第二种策略有关??为什么数学还没学到期望的孩子们都A了? 唉.人生啊. 0.5h后 我好像 ...
- Oracle更新数据为MD5加密数据
业务场景:在做安全等保问题,需要将原来保存的用户明文密码改成md5加密的密文密码,数据库是Oracle的 首先Oracle要管理员账号登录才可以调md5函数,具体函数是DBMS_OBFUSCATION ...
- 基于 CODING 轻松搞定持续集成
点击观看视频教程 带你一步一步搞定 CODING 持续集成 持续集成加速软件交付 持续集成这个概念是由 Grady Booch 在 1991 年首次提出,随后成为了 DevOps 的核心实践之一.持续 ...
- influxdb数据库的安装部署(windows)二
1.把下载好的文件解压到目录中 2.以管理员身份运行cmd进入influxdb-1.7.6-1文件夹 3.生成influxdb数据的默认配置Config文件 4.修改Config配置信息 5.用配置好 ...
- 在IDEA中使用JSP中的out内置对象,out.println()——println红色解决方法
今天在学习JSP的时候,在jsp中使用out内置对象,开发工具用的是IDEA,结果如下图所示 郁闷了半天找度娘,可能关键字输的不准确,乱七八糟的方法一大堆,什么加依赖啊啥的,反正都不管用,最后找到一篇 ...
- iOS bounds vs frame
斯坦福iOS开发课程的白胡子大叔的PPT解释得淋漓尽致!
- iOS 将WKWebView内的HTML打印为PDF
使用的webview为WKWebView,核心部分代码(Swift 4): // 创建打印渲染 let printPageRenderer:PDFRender = PDFRender() // 获取渲 ...
- bzoj1024 [SCOI2009]生日快乐【dfs】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1024 普通的深搜. #include <cstdio> #include < ...
- Kruskal HDOJ 1863 畅通工程
题目传送门 /* 此题为:HDOJ 1233 + HDOJ 1232 */ #include <cstdio> #include <algorithm> #include &l ...
- 1-6static关键字
static的作用? static可以修饰变量,被static修饰的变量叫做静态变量,程序运行时静态变量存放在方法区里面,因此,静态变量在类加载阶段赋值,并且只赋值一次.请看例1 static可以修饰 ...