mysql系列——优化sql及sql练习(十二)

如何优化sql?

开启数据库慢查询日志,定位到查询效率比较低的sql 并分析

1.查看sql语句是否规范

  (1)避免使用关键字:or ,in,not in ,!=,<>,避免使用select *

  (2)尽量避免子查询,大部分子查询都可以连接查询

  (3)用到or的地方可以使用union去代替实现

  (4)用到in的地方可以考虑使用exists去代替 

      in适合于外表大而内表小的情况,exists适合于外表小而内表大

2.查看表中是否存在大量的冗余字段,字段数据类型是否合理

  (1) 比如能用数值的绝对不用字符存储,使用varchar代替char 

  (2)尽量避免null值,使用默认值替代空值,数值型可以使用0,字符型可以使用空字符串

3.分析sql的索引是否可以用

  (1) explain查询sql的执行计划,重点关注的几个列就是,type是不是全表扫描

  (2)看一下索引是否能够用的上,主要看key使用的是哪个索引

  (3)看一下rows扫描行数是不是很大

sql练习

试题.删除一张表中重复记录,重复记录中保留id小的记录

DROP TABLE IF EXISTS `tb_coupon`;
CREATE TABLE `tb_coupon` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '优惠卷id',
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '优惠卷名称',
`type` enum('1','2','3') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '优惠卷类型,1、抵扣 2、折扣(打折)',
`condition` bigint(20) NULL DEFAULT 0 COMMENT '抵扣或折扣条件,如果没有限制,则设置为0',
`reduction` bigint(20) NULL DEFAULT 0 COMMENT '优惠金额',
`discount` int(3) NULL DEFAULT 100 COMMENT '如果没有折扣,为100。如果是八五折,折扣为85',
`targets` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '优惠券可以生效的sku的id拼接,以,分割',
`stock` int(6) NOT NULL COMMENT '剩余优惠券数量',
`start_time` datetime NOT NULL COMMENT '优惠券生效时间',
`end_time` datetime NOT NULL COMMENT '优惠券失效时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '优惠卷表' ROW_FORMAT = Compact;

INSERT INTO `tb_coupon` VALUES (1, 'uuu', '1', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');
INSERT INTO `tb_coupon` VALUES (2, 'uuu', '1', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');
INSERT INTO `tb_coupon` VALUES (3, 'ddd', '2', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');
INSERT INTO `tb_coupon` VALUES (4, 'ddd', '2', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');
INSERT INTO `tb_coupon` VALUES (5, 'eee', '2', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');
INSERT INTO `tb_coupon` VALUES (6, 'eee', '3', 0, 0, 100, '', 2, '1000-01-01 00:00:00', '1000-01-01 00:00:00');

答案:delete from tb_coupon where name in (select name from(select name from tb_coupon group by name HAVING count(name)>1)a )

   and id not in(select id from(select min(id) as id from tb_coupon GROUP BY name HAVING count(name)>1)b);

注意:不能将直接查出来的数据当做删除数据的条件,我们应该先把查出来的数据作为一张临时表,然后再把临时表作为条件进行删除功能

 

试题:统计出当前各个title类型对应的员工当前薪水对应的平均工资

 

select avg(s.salary),t.title from salaries  s join titles  t on s.emp_no=t.emp_no group by t.title

注意:连表之后根据连接条件group by,salary字段也被分组

 

试题.用一条SQL 语句 查询出每门课都大于80 分的学生姓名

name   kecheng   fenshu
张三    语文       81
张三     数学       75
李四     语文       76
李四     数学       90
王五     语文       81
王五     数学       100
王五     英语       90
A: select distinct name from table where name not in (select distinct name from table where fenshu<=80)

B: select name from table group by name having min(fenshu)>80

 

试题请你查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

select * from  employees where emp_no % 2 = 1 and last_name<>'Mary' order by  hire_date desc;

注意:emp_no % 2取余后为1也可以改成MOD(emp_no, 2)=1,但是某些sql版本可能不支持后者

          不相等有三种表示方式:<>、!=、IS NOT

 

试题删除除了自编号不同, 其它都相同的学生冗余信息

学生表 如下:

编号   学号          姓名   课程编号 课程名称   分数
1        2005001   张三   0001         数学         69
2        2005002   李四   0001         数学         89
3        2005001   张三   0001         数学         69

A: delete from table where 编号 not in(select min( 编号) from table group by学号, 姓名, 课程编号, 课程名称, 分数)

注意:可以根据多个字段分组

 

试题.一个叫 team 的表,里面只有一个字段name, 一共有4 条纪录,分别是a,b,c,d, 对应四个球队比赛,用一条sql 语句查出所有可能的比赛组合.
你先按你自己的想法做一下,看结果有我的这个简单吗?

答:select a.name, b.name from team a, team b where a.name < b.name

注意:一张表可以用使用不同的名字从而多次使用。

 

试题:怎么把这样一个表儿
year   month amount
1991   1     1.1
1991   2     1.2
1991   3     1.3
1991   4     1.4
1992   1     2.1
1992   2     2.2
1992   3     2.3
1992   4     2.4
查成这样一个结果
year m1   m2   m3   m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4 

答案一、
select year, 
(select amount from   aaa m where month=1   and m.year=aaa.year) as m1,
(select amount from   aaa m where month=2   and m.year=aaa.year) as m2,
(select amount from   aaa m where month=3   and m.year=aaa.year) as m3,
(select amount from   aaa m where month=4   and m.year=aaa.year) as m4
from aaa   group by year

 

有两个表A 和B ,均有key 和value 两个字段,如果B 的key 在A 中也有,就把B 的value 换为A 中对应的value
这道题的SQL 语句怎么写?

update b set b.value=(select a.value from a where a.key=b.key) where b.id in(select b.id from b,a where b.key=a.key);

posted @ 2022-08-12 14:35  江南大才子  阅读(216)  评论(0编辑  收藏  举报