您的位置:首页 > 数据库 > MySQL

mysql查询详解

2016-12-26 23:12 260 查看
mysql查询详解 ——以下内容摘自马哥教育课堂

SELECT
SELECT查询流程
客户端SELECT语句<==>查询缓存--缓存未命中-->解释器--预处理器-->解析树(多条访问路径)
-->查询优化器(择优选择路径)-->查询执行计划-->查询执行引擎--API调用存储引擎--数据-->查询执行引擎返回结果并使用哈希储存于查询缓存

select now();这是无需查询缓存的,查询当前缓存

多台MYSQL服务器,如何提高MYSQL的缓存命中率
前端程序可使用一致性哈希算法,目的使同样的SELECT语句将发往同一台MYSQL服务器
也可引入第三方的缓存来缓存SELECT的执行结果而非使用MYSQL自身的缓存。程序中可以指明先到memcached中查询SELECT语句是否有缓存结果,没有则与MYSQL服务器做交互。引入多台memcached时,同样需要使用一致性哈希算法来保证SELECT语句的命中
如果业务规模继续增大,可以使用如下架构
--缓存服务器
应用程序--MYSQL读写分离服务器(自行开发,使用一致性哈希)--MYSQL一主多从服务器架构

SQL语句格式
SELECT ... FROM ... ORDER BY ...
SELECT ... FROM ... GROUP BY ... HAVING ...
SELECT ... FROM ... WHERE ...
SELECT ... FROM ... HAVING ...

SELECT语句完整执行流程
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... SELECT 字段 LIMIT ...
WHERE是选择,“SELECT字段”是投影

===
MYSQL单表查询——SELECT详解
HELP SELECT
DISTINCT:数据去重复
SELECT DISTINCT Gender FROM students;
SQL_CACHE:显示指定存储查询结果于缓存之中
SQL_NO_CACHE:显示指定存储查询结果不予缓存
SELECT的结果符合缓存条件即会缓存,否则,不予缓存
查询缓存有相关参数
SHOW GLOBAL VARIABLES LIKE 'query%';
query_cache_type ON:查询缓存功能打开
query_cache_type DEMAND:由命令中指定是否要缓存,SQL_CACHE才会缓存
query_cache_size 16M:默认,可以引入memcached
缓存命中率:查询命中次数/查询总次数
SHOW GLOBAL STATUS LIKE 'Qcache%';查询命中次数
Qcache_hits 2;
SHOW GLOBAL STATUS 'Com_se%';查询总次数
Com_select 42;
查询缓存需要预热后才能提升命中率

字段显示别名:col1 AS alias1,仅显示时修改
SELECT Name AS StuName FROM students;

WHERE子句,指明过滤条件以实现选择的功能;布尔型
算术操作符:+,-,*,/,%
比较操作符:=,!=,<>,<=>;空值安全比较>,>=,<,<=
SELECT Name,Age FROM students WHERE Age+30 > 50;

BETWEEN 下限 AND 上限
IN (元素1,元素2)
SELECT Name,Age FROM students WHERE Age IN (18,100)

IS NULL/IS NOT NULL:判断取值是否为空
SELECT Name,ClassID FROM students WHERE ClassID IS NULL;
SELECT Name,ClassID FROM students WHERE ClassID = NULL;(错误)

LIKE:模糊匹配,可以使用通配符%表示任意多个字符,_任意单个字符
RLIKE:不熟练不用
REGEXP:不熟练不用,匹配字符串可使用正则表达式书写模式

逻辑操作符:NOT, AND, OR, XOR

GROUP:根据指定的条件把查询结果进行“分组”以用于“聚合”运算
avg(),max(),min(),count(),sum()
SELECT avg(Age),Gender FROM students GROUP BY Gender;
按性别分组,那么每组的话有若干个人,计算平均年龄

SELECT avg(Age) as AAge,Gender FROM students GROUP BY Gender HAVING AAge>20;
只显示平均年龄>20分组

SELECT count(StuID) AS NumberOfStu FROM students GROUP BY ClassID;
SELECT count(StuID) AS NumberOfStu,ClassID FROM students GROUP BY ClassID;
统计每个班级多少个同学
SELECT count(StuID) AS NumberOfStu,ClassID FROM students GROUP BY ClassID HAVING NumberOfStu>2;
统计每个班级多少个同学,并只显示班级人数2个以上的

HAVING: 对分组聚合运算后的结果指定过滤条件;

ORDER BY:根据指定的字段对查询结果进行排序;
升序:ASC,降序:DESC
SELECT count(StuID) AS NumberOfStu,ClassID FROM students GROUP BY ClassID HAVING NumberOfStu>2 ORDER BY NumberOfStu [DESC];

LIMIT [[offset,]row_count]: 对显示的结果限制行数
SELECT Name,Age FROM students ORDER BY Age DESC LIMIT 10;
SELECT Name,Age FROM students ORDER BY Age DESC LIMIT 9,10;去掉前面9个后再取10个

FOR UPDATE:对查询结果中的数据施加“写锁”,“排他锁”,其他用户无法读写
LOCK FOR SHARE MODE:对查询结果中的数据施加“读锁”,其他用户只能读

练习:54min

多表查询
交叉连接:笛卡尔乘积,最消耗资源。通常表间连接是两表之间按照指定字段的关系进行连接
SELECT * FROM students,teachers;
students表行数*teachers表行数

等值连接:最常用的方式
笛卡尔乘积的连接其实没什么意义,那怎样连接才是有意义的呢?students表中的TeacherID和teachers表中的TID代表的都是老师ID,是相同意义的,所以可以根据此字段进行表连接
SELECT * FROM students,teachers WHERE students.TeacherID=teachers.TID;

此时,可以只显示特定字段形成对应关系,查找某同学对应的老师
SELECT s.Name AS StuName,t.Name AS TeaName FROM students AS s,teachers AS t WHERE s.TeacherID=t.TID; 表也可以取别名
EXPLAIN SELECT s.Name AS StuName,t.Name AS TeaName FROM students AS s,teachers AS t WHERE s.TeacherID=t.TID\G

SELECT * FROM students;
SELECT * FROM classes;这两个表都有ClassID字段,综合这两个表查询学生和班级名的对应关系
SELECT s.Name,c.Class FROM students AS s,classes AS c WHERE s.ClassID=c.ClassID;

除此之外,还有不等值连接,自然连接。以上两者加上等值连接三者称为内连接

外连接
左外连接:左表等值连接右表时,如果左表某行数据对应右表的字段为空,那么也要显示左表的该行数据
SELECT s.Name,c.Class FROM students AS s,classes AS c WHERE s.ClassID=c.ClassID;即使没有班级的学生也要显示其名字,而不是不显示
FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col

SELECT s.Name,c.Class FROM students AS s LEFT JOIN classes AS c WHERE s.ClassID=c.ClassID;最后结果包含
**** NULL
**** NULL

右外连接:左表等值连接右表时,如果右表某行数据对应左表的字段为空,那么也要显示右表的该行数据
FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col
SELECT s.Name,c.Class FROM students AS s RIGHT JOIN classes AS c WHERE s.ClassID=c.ClassID;
NULL ****
NULL ****

全外连接:结合左外连接和右外连接
NULL ****
NULL ****
**** NULL
**** NULL

自连接,用表中某字段和另一字段的等值关系建立连接
SELECT s.Name,t.Name FROM students AS s,students AS t WHERE s.TeacherID=t.StuID;

子查询:基于某语句的查询结果再次查询,类似视图
不建议使用,因为MYSQL子查询的实现不佳
=
用在WH ERE子句中的子查询
(1)用于比较表达式的子查询:子查询仅能返回单个值;
查询大于平均年龄的学生
SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM students;)
EXPLAIN SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM students;)\G

(2)用在IN中的子查询:子查询应该返回一个或多个值构成列表;
老师年龄和学生年龄相同的
SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);

(3)用于EXISTS

=
用于FROM子句中的子查询,这个和视图类似,视图是把查询句子存储下来了,FROM子查询是没有存
使用格式:SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;

SELECT AAge,ClassID FROM (SELECT avg(Age) AS AAge,ClassID FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;

===
联合查询
SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 查询 过程