数据库进阶(2)

union

UNION操作符用于合并两个或者多个select语句的结果集。
使用 UNION 关联的select语句必须拥有相同数量的列,列也必须拥有相似的数据类型。同时,每条select语句中的列的顺序必须相同。

语法:

select 列名[1,2...] from 表
union
select 列名[1,2...] from 表2</pre>

默认地,union操作符选取不同的值,即union是去了重的。如果允许重复的值,可以使用union all。

union all

同样是合并结果集,但是union all不会去重
语法:

select 列名[1,2...] from 表
union all
select 列名[1,2...] from 表2

实战:

查询两张订单表中的orderid,不允许重复:

select order_id
from order_1
union
select order_id
from order_2;

查询两张订单表中的所有orderid

select order_id
from order_1
union all
select order_id
from order_2;

order by

将查询结果 按照某个字段或多个字段 进行升序或者降序 排列

语法:

select 字段1,字段2...
from 表
order by 字段1,字段2... asc/desc;
asc: 代表升序排列,从小到大
desc : 代表降序排列,从大到小
默认是升序排列,asc可以不写

实战:

查询student表,按照生日降序排列

select * from student
order by birthday desc ;

查询student表,按照生日升序排列

select * from student
where birthday is not null
order by birthday ;

group by

GROUP BY 语句根据一个或多个列对结果集进行分组。

在分组的列上可以使用聚合函数查询。

语法:

SELECT 字段, 聚合函数(字段)
FROM 表
WHERE 条件
GROUP BY 字段;

实战

查询每个学生成绩最高的分数是多少?

解析: 每个学生的分数,就是按照学生分组,然后统计每个学生考试科目的最高分

select a.sid,a.sname,max(s.score) from student a inner join sc s on a.sid = s.sid
group by a.sid;

查询各科目成绩最好的分数是多少,展示科目和成绩:
select c.cname,max(s.score)
from sc s
inner join course c on s.cid = c.cid
group by s.cid;

having

having 用于对分组数据的再次过滤,必须紧跟 group by 子句之后,不能单独使用. having的条件必须是聚合函数
语法:
SELECT 字段,聚合函数(字段)
FROM 表
WHERE 字段=xxx
GROUP BY 字段
HAVING 聚合函数(字段) › /‹ /=值

实战:

查出所有学生中只参加了两门考试的学生

select s.sid,s.sname from student s inner join sc s2 on s.sid = s2.sid
group by s.sid
having count(*) =2;

image.png

时间函数

MySQL提供了很多用于处理时间的函数,比如获取当前时间,计算两个日期的差值,获取时间的年,月,周等等

制造测试数据

下载sql脚本并执行
https://guoya-data2.oss-cn-hangzhou.aliyuncs.com/guoya-data/wikiAcc/20200721/4rfvx_order1.sql

now() 和 sysdate()

这两个函数都是返回当前时间的

select now(), sysdate();

区别:
now(): 是返回sql语句开始执行时的时间,是一个常量
sysdate(): 是返回 函数执行时的时间

举个例子:

SELECT NOW(), SLEEP(5), NOW();</pre>

SLEEP(5) : 等待5秒
可以看到等待前后的时间 是一样的

image.png

SELECT sysdate(), SLEEP(5), sysdate();</pre>

sysdate() 函数是执行时的时间,可以看到两个时间相差5秒


image.png

datediff()

计算两个时间之间相差的天数

实战:

查询order_1表中 create_time 与当前时间 相差的天数

select *, datediff(now(),create_time) from order_1;

查询 order_1表中 20天内的订单
select * from order_1 where datediff(now(),create_time) ‹ 20;

dayofweek() 和 weekday()

dayofweek() : 查询 时间 是周几,返回 的是 索引

1 代表周日
2 代表周一
以此类推
7 代表周六

实战:

查询今天是周几
select dayofweek(now());

查询每周日的订单

select * from order_1 where dayofweek(create_time) =1;

weekday() : 查询 时间 是周几,返回 的同样是 索引

不过索引值从 0开始
星期一为0,星期二为1,以此类推,星期日为6

dayname()

返回指定日期 是周几,不以索引展示,而是文字

实战:

查询今天是周几

select dayname(now());


image.png

可以看到展示的是英文
修改为中文:

set @@lc_time_names='zh_CN';
再次查询:

image.png

查询student表学生的生日 都是周几

select *,dayname(birthday) from student;

day()

返回 日期 是几号.

week()

返回 日期 是 当年的第几周

month()

返回 日期 的 月份

year()

返回 日期 的年份

实战

查询order_1表 每月1号 的订单

select *
from order_1
where day(create_time) = 1;

查询 order_1表 在2019年1月哪一天的订单数量最高?

select day(create_time), count (* )
from order_1
where year(create_time) = 2019
and month(create_time) = 1
group by day(create_time)
having count(* ) = (
select count(* )
from order_1
where year(create_time) = 2019
and month(create_time) = 1
group by day(create_time)
order by count(* ) desc
limit (1);

查询 order_1表 在2019年 每周的订单数量(*)

select week(create_time), count(*) from order_1
where year(cr8eate_time) = 2019
group by week(create_time);

查询 order_1表 在2019年 每月的订单数量,并将数量按倒叙排列

select month(create_time), count(* ) from order_1
where year(create_time) = 2019
group by month(create_time)
order by count(*) desc;

查询 order_1表 每年的订单数量

select year(create_time), count(*) from order_1
group by year(create_time);

explain

在进行sql语句优化时,可使用explain关键字查看sql执行计划,从而知道MySQL是如何处理sql语句的,可以分析性能瓶颈及优化

举例:

explain select * from sc where sid = (select sid from student where sname = '周梅');

image.png

可以看到一共有12列信息

id :

id相同,执行顺序从上往下,id不同,id值越大,优先级越高,越先执行

select_type :

查询类型
1、simple ——简单的select查询,查询中不包含子查询或者UNION
2、primary ——查询中若包含任何复杂的子部分,最外层查询被标记
3、subquery——在select或where列表中包含了子查询
4、derived——在from列表中包含的子查询被标记为derived(衍生),MySQL会递归执行这些子查询,把结果放到临时表中
5、union——如果第二个select出现在UNION之后,则被标记为UNION,如果union包含在from子句的子查询中,外层select被标记为derived
6、union result:UNION 的结果

table:

引用的表

partitions

分区表的命中情况,不是分区表则为null

type

从最好到最差的连接类型依次为:

system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL

system:
系统表,表中只有一行数据
const:
读常量,最多只会有一条记录匹配,由于是常量,实际上只需要读一次。
eq_ref:
最多只会有一条匹配结果,一般是通过主键或唯一键索引来访问
ref:
对于来自前面表的每一行,在此表的索引中可以匹配到多行。若联接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此联接能够匹配多行记录)。
fulltext:
使用全文索引的时候是这个类型。要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
ref_or_null:
跟ref类型类似,只是增加了null值的比较。实际用的不多。
index_merge:
表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range
unique_subquery:
用于where中的in形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。
index_subquery:
子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或唯一索引
range:
索引范围查询,常见于使用 =, ‹›, ›, ›=, ‹, ‹=, IS NULL, ‹=›, BETWEEN, IN()或者like等运算符的查询中。
index:
索引全表扫描,把索引从头到尾扫一遍
all:
全表扫描,性能最差。

possible_keys

可能使用到的索引

key

实际使用的索引

key_len

使用索引的字节数,只展示where使用到的,排序和分组使用的索引不计入

ref

如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func

rows

mysql估算的需要扫描的行数(不是精确值),越小越好

filtered

最终展示的结果条数 占 扫描的条数的百分比, 越大越好

extra

辅助描述信息,常见信息:

  • using index : 出现这个说明mysql使用了覆盖索引,避免访问了表的数据行,效率不错。

  • using where :这说明服务器在存储引擎收到行后讲进行过滤。

  • using temporary :这意味着mysql对查询结果进行排序的时候使用了一张临时表

  • using filesort :这个说明mysql会对数据使用一个外部的索引排序
    注意当出现using temporary 和 using filesort时候说明需要优化操作

总结

sql优化时,先看 type 尽量将连接类型提高,可以通过加索引或者优化查询条件等, 其次再优化 rows 和 filtered 字段。

explain中id越大优先级越高还是越低? 越高
explain中type字段的字段值:range,index,ALL,ref,const,按照从好到差排列
const ,ref ,range,index,ALL
explain中rows的值 越大越好,还是越小越好?越小越好
explain中filtered的值 越大越好,还是越小越好?越大越好

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353