首页 > 代码库 > mysql查询详解

mysql查询详解

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查询详解