mysql面试题执行顺序_mysql 经典面试题以及优化过程

CREATE TABLE `t_dept` (

`id` INT(11) NOT NULL AUTO_INCREMENT,

`deptName` VARCHAR(30) DEFAULT NULL,

`address` VARCHAR(40) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `t_emp` (

`id` INT(11) NOT NULL AUTO_INCREMENT,

`name` VARCHAR(20) DEFAULT NULL,

`age` INT(3) DEFAULT NULL,

`deptId` INT(11) DEFAULT NULL,

empno int not null,

PRIMARY KEY (`id`),

KEY `idx_dept_id` (`deptId`)

#CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)

) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO t_dept(deptName,address) VALUES('华山','华山');

INSERT INTO t_dept(deptName,address) VALUES('丐帮','洛阳');

INSERT INTO t_dept(deptName,address) VALUES('峨眉','峨眉山');

INSERT INTO t_dept(deptName,address) VALUES('武当','武当山');

INSERT INTO t_dept(deptName,address) VALUES('明教','光明顶');

INSERT INTO t_dept(deptName,address) VALUES('少林','少林寺');

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('风清扬',90,1,100001);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('岳不群',50,1,100002);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('令狐冲',24,1,100003);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('洪七公',70,2,100004);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('乔峰',35,2,100005);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('灭绝师太',70,3,100006);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('周芷若',20,3,100007);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('张三丰',100,4,100008);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('张无忌',25,5,100009);

INSERT INTO t_emp(NAME,age,deptId,empno) VALUES('韦小宝',18,null,100010);

ALTER TABLE `t_dept` add CEO INT(11) ;

update t_dept set CEO=2 where id=1;

update t_dept set CEO=4 where id=2;

update t_dept set CEO=6 where id=3;

update t_dept set CEO=8 where id=4;

update t_dept set CEO=9 where id=5;

下面的emp 和 dept表是用存储过程向 emp表添加了50w条数据,dept添加了10w条数据

1),列出自己的掌门比自己年龄小的人员

select e.name,e.age,e1.name,e1.age from t_emp e

left join t_dept d on e.deptId = d.id

left join t_emp e1 on d.ceo =e1.id

where e.age > e1.age;

换成大表explain 优化查询

explain select e.name,e.age,e1.name,e1.age from emp e

left join dept d on e.deptId = d.id

left join emp e1 on d.ceo =e1.id

where e.age > e1.age;

2),列出所有年龄低于自己门派平均年龄的人员

-- 求出所有门派平均年龄

select deptId,avg(age) ag from t_emp group by deptId;

select e.name,e.age,e1.ag,e1.age from t_emp e inner join (select deptId,avg(age) ag,age from t_emp where deptId is not null group by deptId) e1 on e.deptId=e1.deptId where e.age < e1.age;

优化:

2-1), 执行explain

explain select SQL_NO_CACHE e.name,e.age,e1.ag,e1.age from emp e

inner join (select deptId,avg(age) ag,age from emp where deptId is not null group by deptId) e1

on e.deptId=e1.deptId

where e.age < e1.age;

2-2), 为dept 表的 group by 后面字段增加索引

create index idx_emp_deptId on emp(deptId);

2-3),为emp表的 deptId 建立索引和 age有了范围查询索引也建立索引

create index idx_emp_deptIdAge on emp(deptId,age);

2-4),再次执行explain ,优化完成

3),列出至少有2个年龄大于40岁的成员的门派(少林寺有南少林和北少林索引分组时应该注意)

select d.deptName,d.id,count(1) from t_emp e

inner join t_dept d

on e.deptId = d.id

where e.age>40

group by d.deptName,d.id

having count(1) >= 2 ;

优化:

3-1),explain 查看 使用 STRAIGHT_JOIN

explain

select d.deptName,d.id,count(1) from dept d

STRAIGHT_JOIN emp e

on e.deptId = d.id

where e.age>40

group by d.deptName,d.id

having count(1) >= 2 ;

​​​​​​STRAIGHT_JOIN 什么时候可以用?

1明确STRAIGHT_JOIN的概念(指定谁是驱动表谁是被驱动表),例如 a表 STRAIGHT_JOIN  b表 这里 a表是驱动表 b表是北驱动表,注意 小表驱动大表

明确前后俩个表的数量级关系

3-2), 给 dept表的 再给 group by 字段建立索引,因为id 为主键索引不用添加索引

create index idx_dept_deptName on dept(deptName);

3-3), 给emp表的deptId 和 age 也添加索引

create index idx_dept_deptIdAge on emp(deptId,age);

3-4),执行 explain 语句 优化完成

​​​​​​​4),至少有俩个非掌门人成员的门派

select d.deptName,d.id from t_emp e

inner join dept d1 on e.deptId = d1.id

left join t_dept d on e.id = d.ceo

where d.id is null

group by d.deptName,d.id

having count(1)>=2

优化:

4-1), explain 使用 STRAIGHT_JOIN 指定那个表为驱动表

explain select d.deptName,d.id from dept d1

STRAIGHT_JOIN emp e on e.deptId = d1.id

left join dept d on e.id = d.ceo

where d.id is null

group by d.deptName,d.id

having count(1)>=2

4-2),为 dept 表添加添加索引

create index idx_dept_deptName on dept(deptName);

create index idx_dept_ceo on dept(ceo);

4-3),为 emp表添加索引

create index idx_emp_deptId on emp(deptId);

4-4),再次使用 explain 执行sql语句,优化完成

5),列出全部人员,并增加一列备注为 是否为 掌门人 如果是掌门人显示是 否则 否 条件是

#方式1

select e.name,if(d.id is null ,'否','是') 是否为掌门人

from t_emp e

left join t_dept d

on e.id=d.ceo;

#方式2

select

e.name,

case when d.id is null then '否' else '是' end 是否为掌门人

from t_emp e

left join t_dept d

on

e.id=d.ceo;

6),列出全部门派,增加一列备注 老鸟or菜鸟 门派平均年龄大于50显示老鸟否则菜鸟

select d.deptName, if(avg(e.age)>50,'老鸟','菜鸟') 老鸟or菜鸟 from t_dept d

inner join t_emp e

on d.id=e.deptId

group by d.deptName,d.id

7),显示每个门派年龄最大的人

select e.name,e.age, max(age) mx from t_emp e

inner join t_dept d

on e.deptId=d.id

group by d.deptName,d.id

having mx

8),显示每个门派年龄第二大的人(sql编程)

set @rank =0; #定义变量 -排名

set @last_deptId=0; #下一个部门id

set @last_age=0; #定义年龄变量

select e.name,e.age,e.deptId from (

select e.*,

if(

@last_deptId = deptId,

if(@last_age = age,@rank,@rank:=@rank+1),

@rank:=1) as rk,

@last_deptId:=deptId as last_deptId,

@last_age:=age as last_age

from t_emp e order by e.deptId,e.age desc) e

where e.rk =2;

本文地址:https://blog.csdn.net/qq_40646143/article/details/108993956

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值