mysql联表多条去重_MySQL高级

本文详细介绍了MySQL的联表查询、去重操作以及索引的使用和管理,包括七种JOIN方式的实践,索引对查询速度的提升,以及如何避免索引失效。通过对SQL执行计划的分析,揭示了SQL查询的执行顺序和效率优化策略,旨在帮助读者深入理解MySQL的高级用法。
摘要由CSDN通过智能技术生成

本文大纲

94129eca0b76c73738284e277263703d.png

环境

  • win10-64

  • MySQL Community Server 5.7.1

    mysqld –version可查看版本

  • 官方文档

SQL执行顺序

手写顺序

我们可以将手写SQL时遵循的格式归结如下:

select distinct
    from  join  on wheregroup byhavingorder bylimit <offset>,<rows>
  • distinct,用于对查询出的结果集去重(若查出各列值相同的多条结果则只算一条)

  • join,关联表查询,若将两个表看成两个集合,则能有7种不同的查询效果(将在下节介绍)。

  • group by,通常与合计函数结合使用,将结果集按一个或多个列值分组后再合计

  • having,通常与合计函数结合使用,弥补where条件中无法使用函数

  • order by,按某个标准排序,结合asc/desc实现升序降序

  • limit,如果跟一个整数n则表示返回前n条结果;如果跟两个整数m,n则表示返回第m条结果之后的n条结果(不包括第m条结果)

MySQL引擎解析顺序

而我们将SQL语句发给MySQL服务时,其解析执行的顺序一般是下面这样:

from
    
on
    
 join
    
where
    
group by
    
having
    
select
    
order by
    
limit
    offset,rows
feca5225c7d93dbf94b75189662c0832.png

了解这个对于后续分析SQL执行计划提供依据。

七种Join方式

22ebf549ac74202a300142c7b388b648.png

下面我们创建部门表tbl_dept和员工表tbl_emp对上述7种方式进行逐一实现:

  • 部门表:主键id、部门名称deptName,部门楼层locAdd

mysql> CREATE TABLE `tbl_dept` (
    ->  `id` INT(11) NOT NULL AUTO_INCREMENT,
    ->  `deptName` VARCHAR(30) DEFAULT NULL,
    ->  `locAdd` VARCHAR(40) DEFAULT NULL,
    ->  PRIMARY KEY (`id`)
    -> ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  • 员工表:主键id,姓名name、所属部门deptId

mysql> CREATE TABLE `tbl_emp` (
    ->  `id` INT(11) NOT NULL AUTO_INCREMENT,
    ->  `name` VARCHAR(20) DEFAULT NULL,
    ->  `deptId` INT(11) DEFAULT NULL,
    ->  PRIMARY KEY (`id`),
    ->  KEY `fk_dept_id` (`deptId`)
    ->  #CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `tbl_dept` (`id`)
    -> ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

插入一些测试数据:

mysql> INSERT INTO tbl_dept(deptName,locAdd) VALUES('技术部',11);
Query OK, 1 row affected (0.07 sec)

mysql> INSERT INTO tbl_dept(deptName,locAdd) VALUES('美工部',12);
Query OK, 1 row affected (0.08 sec)

mysql> INSERT INTO tbl_dept(deptName,locAdd) VALUES('总裁办',13);
Query OK, 1 row affected (0.06 sec)

mysql> INSERT INTO tbl_dept(deptName,locAdd) VALUES('人力资源',14);
Query OK, 1 row affected (0.11 sec)

mysql> INSERT INTO tbl_dept(deptName,locAdd) VALUES('后勤组',15);
Query OK, 1 row affected (0.10 sec)

mysql> insert into tbl_emp(name,deptId) values('jack',1);
Query OK, 1 row affected (0.11 sec)

mysql> insert into tbl_emp(name,deptId) values('tom',1);
Query OK, 1 row affected (0.08 sec)

mysql> insert into tbl_emp(name,deptId) values('alice',2);
Query OK, 1 row affected (0.08 sec)

mysql> insert into tbl_emp(name,deptId) values('john',3);
Query OK, 1 row affected (0.13 sec)

mysql> insert into tbl_emp(name,deptId) values('faker',4);
Query OK, 1 row affected (0.10 sec)

mysql> insert into tbl_emp(name) values('mlxg');
Query OK, 1 row affected (0.13 sec)

mysql> select * from tbl_dept;
+----+----------+--------+
| id | deptName | locAdd |
+----+----------+--------+
|  1 | 技术部   | 11     |
|  2 | 美工部   | 12     |
|  3 | 总裁办   | 13     |
|  4 | 人力资源 | 14     |
|  5 | 后勤组   | 15     |
+----+----------+--------+
5 rows in set (0.00 sec)

mysql> select * from tbl_emp;
+----+-------+--------+
| id | name  | deptId |
+----+-------+--------+
|  1 | jack  |      1 |
|  2 | tom   |      1 |
|  3 | alice |      2 |
|  4 | john  |      3 |
|  5 | faker |      4 |
|  7 | ning  |   NULL |
|  8 | mlxg  |   NULL |
+----+-------+--------+
7 rows in set (0.00 sec)

两表的关联关系如图所示:

4ff962361a7a5a344ae850e76f367d14.png

1、左连接(A独有+AB共有)

查询所有部门以及各部门的员工数:

mysql> select t1.id,t1.deptName,count(t2.name) as emps from tbl_dept t1 left join tbl_emp t2 on t2.deptId=t1.id group by deptName order by id;
+----+----------+------+
| id | deptName | emps |
+----+----------+------+
|  1 | 技术部   |    2 |
|  2 | 美工部   |    1 |
|  3 | 总裁办   |    1 |
|  4 | 人力资源 |    1 |
|  5 | 后勤组   |    0 |
+----+----------+------+
5 rows in set (0.00 sec)

2、右连接(B独有+AB共有)

查询所有员工及其所属部门:

mysql> select t2.id,t2.name,t1.deptName from tbl_dept t1 right join tbl_emp t2 on t2.deptId=t1.id;
+----+-------+----------+
| id | name  | deptName |
+----+-------+----------+
|  1 | jack  | 技术部   |
|  2 | tom   | 技术部   |
|  3 | alice | 美工部   |
|  4 | john  | 总裁办   |
|  5 | faker | 人力资源 |
|  7 | ning  | NULL     |
|  8 | mlxg  | NULL     |
+----+-------+----------+
7 rows in set (0.04 sec)

3、内连接(AB共有)

查询两表共有的数据:

mysql> select deptName,t2.name empName from tbl_dept t1 inner join tbl_emp t2 on t1.id=t2.deptId;
+----------+---------+
| deptName | empName |
+----------+---------+
| 技术部   | jack  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值