mysql基础总结
1. mysql 执行顺序
1.1 sql 语句的执行顺序
from…left join … on… where…group by…聚合函数… having…select…order by… limit…
1.2 易混淆1:
order by作用于源表和生成的结果集 所以可以针对select 没有映射到的列进行排序,也可以针对select映射到的列使用新的虚拟表的字段名进行排序。
select name as studentName from student order by [name/studentName]
都行。
1.3 易混淆2
对于where执行顺序
where执行顺序是从左往右执行的,在数据量小的时候不用考虑,但数据量多的时候要考虑条件的先后顺序,此时应遵守一个原则:排除越多的条件放在第一个。
以上说法其实没必要过多关注,mysql不一定会按照我们手写的顺序从左到右执行,而是mysql本身的优化器会帮助我们重写sql语句,通过explain 和 show waings 可以看到重写的sql语句。
同样的,mysql 优化器也会将 select From a , b 重写为 select * a join b
2. join原理
2.1 Join执行原理解析
一个完整的SQL语句中会被拆分成多个子句,子句的执行过程中会产生虚拟表(vt),但是结果只返回最后一张虚拟表
FROM:对左右两张表执行笛卡尔积,产生第一张表vt1。行数为n*m(n为左表的行数,m为右表的行数
ON:根据ON的条件逐行筛选vt1,将结果插入vt2中
JOIN添加外部行:,如果指定了LEFT JOIN(LEFT OUTER JOIN),则先遍历一遍左表的每一行,其中不在vt2的行会被插入到vt2,该行的剩余字段将被填充为NULL,形成vt3;如果指定了RIGHT JOIN也是同理。但如果指定的是INNER JOIN,则不会添加外部行,上述插入过程被忽略,vt2=vt3(所以INNER JOIN的过滤条件放在ON或WHERE里 执行结果是没有区别的)
WHERE:对vt3进行条件过滤,满足条件的行被输出到vt4
SELECT:取出vt4的指定字段到vt5
2.2 牢记on和where的区别
on是连接的时候进行筛选,没有连接成功的还是会添加外部行到结果集中,但是where是对结果集进行筛选,会对所有的结果集进行筛选。
3.注意点总结
3.1 语法
1.聚合函数count() 需要注意的点。
count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
2.between 包含边界值 not between 不包含边界值
4.常见错误sql及解决
4.1 组内最大
order by + group by
即使是有嵌套也是先执行group by 再执行order by 这也就是不能使用order by + group 取得组内最大值的原因 group by是对表中原来的字段进行分组的***,而不是处理之后的数据。
正确写法:通过子查询或者join
方法一:
select * from a left join b on a.filed=b.filed where b.createdate=(select max(createdate) from b where b.filed=a.filed)
不能通过order by + group by 取是因为不知道分组取数的原则是什么?
select max(createdate) from b where b.filed=a.filed 此处相当于 select max(createdate) from b group b.filed
方法二:
通过group by 和left join 组合使用
1 | SELECT |
4.2 连接表查询更新
(在想要更改某个表之前,需要先查询同一个表,并根据查询结果进行更改)
例子: 把“SC”表中“叶平”老师教的课的成绩都更改为此课程的平均成绩;
1 | UPDATE student_score set score |
You can’t specify target table ‘student_score’ for update in FROM clause
不能从一张表中查出数据然后再更改同一张表
1 | UPDATE student_score s |
即所有的set select 类型的更新,都可以转化为inner join set 后者再封装一层
4.3 组内取前 (in+limit 报错)
This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME subquery’ mysql
遇到如上错误可以参考我的另一篇总结
https://zhongzhongbaby.github.io/2019/08/29/mysql%E7%BB%84%E5%86%85%E5%8F%96%E5%89%8D/
5.常用函数
5.1 常用函数
1.find_in_set()
有个文章表里面有个type字段,它存储的是文章类型,有 1头条、2推荐、3热点、4图文等等 。type中以 1,3,4 的格式存储,查找所有type中有4的图文类型的文章
select * from article where FIND_IN_SET(‘4’,type)
FIND_IN_SET(str,strlist)
在mysql中,有时我们在做数据库查询时,需要得到某字段中包含某个值的记录,但是它也不是用like能解决的,使用like可能查到我们不想要的记录,它比like更精准
2.concat (拼接字符串)
select concat (id, name, score) as info from tt2; –>1小明0
concat_ws() 指定分隔符 concat_ws(separator, str1, str2, …)
group_concat()将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator ‘分隔符’] )
group_concat 常和 find_in_set 一起使用
3.ifnull(tNumTb.num,0)
返回第一个不为空的值
4.(case when pcOut.season=’1’ then ‘2’ when ….
5.substring()
6.Round(double,2) 四舍五入到指定位数的
7.日期函数
date_ForMate(,’%Y-%m_%d’);
UNiX_TIMESTAMP(create_date)
str_to_date()
datetime类型的比较大小
unix_timestamp(time1) > unix_timestamp(‘2011-03-03 17:39:05’)
time1 between ‘2011-03-03 17:39:05’ and ‘2011-03-03 17:39:52’;
6.技巧经验
straight join 就是为了替换 inner join 驱动表顺序的不可控(由mysql 优化器决定)
使用SQL_CACHE查询
对于那些变化不频繁的表,查询操作很固定,我们可以将该查询操作缓存起来,这样每次执行的时候不实际访问表和执行查询,只是从缓存获得结果,可以有效地改善查询的性能,使用SQL_CACHE 选项
测试sql语句性能使用SQl_NO_CACHEdelete 数据的时候一定要注意。小心把整张表都删除 例如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!-- 删除后补记录数据 -->
<delete id="deleteSignupCandidate">
delete from signup_candidate_info where 1=1
<choose>
<when test="ids != null and ids != ''">
AND id in
<foreach collection="ids.split(',')" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</when>
<otherwise>
AND 1=2
</otherwise>
</choose>
</delete>CONVERT ( trim( a.NAME ) USING gbk ) 按照中文拼音排序, 但是会导致索引失效。
in () 中值很多的时候,mysql优化器会认为全表扫描速度优于索引,如果和事实相反,可以使用force index 强制索引。
数据库设计阶段,不一定一定要严格按照三范式,大表需要经常关联的join数据可以字段冗余,一般就业务逻辑而言,生成一次一般就不会再修改了,但是在查询的时候需要经常查询,那么可以做数据冗余,满足第二范式即可。以空间换时间。
如果业务上需要按照中文姓名排序分页,可以增加姓名拼音字段。因为使用mysql函数,需要转utf8编码为gbk,而且不能使用索引。排序会很慢。
系统在分页的情况下,使用子查询可能比表连接性能高。对于没有分页的数据还是要优秀考虑 (需要考虑在什么情况下会先执行limit 后执行 子查询????????)
left join 并不一定是左边的表是驱动表,而STRAIGHT_JOIN一定是左边的表是驱动表
在find_in_set 不能使用索引的情况下,可以考虑通过代码转换为in查询
Original author: Geng
Original link: https://zhongzhongbaby.github.io/2019/08/28/mysql基础总结/
Copyright Notice: Please indicate the source of the reprint (must retain the author's signature and link)