从多表连接后的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(*)快, 如果有主键 ...
随机推荐
- C++ C# 默认对齐是8字节
C++ C# 默认对齐是8字节 以上,一直以为是4字节,尼玛
- P5169 xtq的异或和(FWT+线性基)
传送门 我咋感觉我学啥都是白学-- 首先可以参考一下这一题,从中我们可以知道只要知道两点间任意一条路径以及整个图里所有环的线性基,就可以得知这两个点之间的所有路径的异或和 然而我好像并不会求线性基能张 ...
- IT兄弟连 Java Web教程 Servlet的生命周期
JavaWeb应用的生命周期由Servlet容器来控制,而Servlet作为JavaWeb应用的最核心的组件,其生命周期也由Servlet容器来控制.Servlet的生命周期可以分为3个阶段:初始化阶 ...
- Linux--------------mysql的安装
工具: 1>Centos6.8 2>Jdk1.7 3>Mysql5.7 1.下载mysql wget http://dev.mysql.com/get/Download ...
- The 17th Zhejiang University Programming Contest Sponsored by TuSimple J
Knuth-Morris-Pratt Algorithm Time Limit: 1 Second Memory Limit: 65536 KB In computer science, t ...
- 洛谷 P2714 四元组统计
错误记录:42行N写成n:事实上除了读入以外,此题的小n没有任何用途 #include<cstdio> #include<algorithm> #include<cstr ...
- Linux Ubuntu 14.04 LTS下VirtualBox连接USB
1.环境 主机:Ubuntu 14.04 LTS 虚拟机:Windows 7 专业版本 VirtualBox: 图形用户界面版本 5.1.8 r111374 (Qt5.6.1) 2.在主机上给Virt ...
- EJB Timer Service is not available. Timers for application with id 95795415990861824 will not be deleted
delete follows:glassfish\domains\domain1\applications\ejb-timer-service-appglassfish\domains\domain1 ...
- 多个版本数据库在在一台数据库上lib 的切换问题。
lib 的切换问题. 现象: /home/dbmon >sqlplus / as sysdba/usr/lib/hpux64/dld.so: Unsatisfied data symbol ' ...
- Finally语句