zoukankan      html  css  js  c++  java
  • mysql高级查询

    Exists子查询

    Exists的特点

             1.在执行createdrop语句前,可以使用exists语句来判断数据库对象是否存在,返回值是truefalse

                 比如  

     drop   table    if  exists  student;  意思是如果存在表student则删除!否则不删除!

     Create  table   if  not  exists  student;   意思是如果不存在表student则创建,否则不创建!

             2.exists还可以作为where条件的子查询

                    Select  ..... from  表名  where  exists (子查询);

                    意思是:

                         如果子查询有结果,则返回值为true,继续执行外层的查询语句;

                         如果子查询没有结果,则返回值是false,外层的查询语句不会执行。

                      

                  

    -- 检查“高等数学-1” 课程最近一次考试成绩

    -- 如果有 80分以上的成绩,显示分数排在前5名的学员学号和分数

    --  不使用exists

    -- 01.查询“高等数学-1” 课程 对应的编号

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    -- 02.查询最近的考试成绩

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    -- 03. 02的基础上 加条件 成绩大于80

    SELECT * FROM result

    WHERE ExamDate=

    (SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'))

    AND StudentResult>80

    -- 04.优化

    SELECT studentNo,StudentResult FROM result

    WHERE ExamDate=

    (SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'))

    AND StudentResult>80

    ORDER BY StudentResult DESC

    LIMIT 0,5

    --  使用exists

    -- 检查“高等数学-1” 课程最近一次考试成绩

    -- 如果有 80分以上的成绩,显示分数排在前5名的学员学号和分数

    -- 01.查询“高等数学-1” 课程 对应的编号

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    -- 02.查询最近的考试成绩

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    -- 03.查询学号和成绩

    SELECT StudentNo,StudentResult FROM result

    WHERE  EXISTS

    (

    SELECT * FROM result

    WHERE subjectNo=(

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    )

    AND ExamDate=(

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    )

    AND StudentResult>80

    )

    AND subjectNo=(

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    )

    AND ExamDate=(

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    )

    ORDER BY StudentResult DESC

    LIMIT 0,5

    Not Exists子查询

    -- 检查“高等数学-1”课程最近一次考试成绩

    -- 如果全部未通过考试(60分及格),认为本次考试偏难,计算的该次考试平均分加5

    -- 01.查询“高等数学-1” 课程 对应的编号

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    -- 02.查询最近的考试成绩

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    -- 03.查询成绩大于60的  反着来

    SELECT StudentResult FROM result

    WHERE StudentResult>60

    AND SubjectNo=(

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    )

    AND ExamDate=(

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    )

    -- 04. 如果全部未通过考试,考试平均分加5

    SELECT AVG(StudentResult)+5  FROM result

    WHERE NOT EXISTS

    (

    SELECT StudentResult FROM result

    WHERE StudentResult>60

    AND SubjectNo=(

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    )

    AND ExamDate=(

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    )

    )

    AND SubjectNo=(

    SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1'

    )

    AND ExamDate=(

    SELECT MAX(ExamDate) FROM result

    WHERE SubjectNo=(SELECT subjectNo FROM `subject`

    WHERE SubjectName='高等数学-1')

    )

    -- 如果有 年级名称是大二 的学生,就 查询出 年级名称是大一的 所有学生信息

    --  01.先查询出 对应的年级编号

    SELECT GradeId FROM grade  WHERE GradeName='大一'

    SELECT GradeId FROM grade  WHERE GradeName='大二'

    --  02.在学生表中是否存在  年级名称是大二 的学生

    SELECT * FROM  student  WHERE  gradeID=(

    SELECT GradeId FROM grade  WHERE GradeName='大二'

    )

    -- 03.如果有查询出 年级名称是大一的 所有学生信息

    SELECT * FROM student

    WHERE  EXISTS

    (

    SELECT * FROM  student  WHERE  gradeID=(

    SELECT GradeId FROM grade  WHERE GradeName='大二'

    )

    )

    AND GradeId=(

    SELECT GradeId FROM grade  WHERE GradeName='大一'

    )

    ExistsIN , Not ExistsNot IN 的区别

     01. INNot IN 做的是一个区间的判断,查询数据是否在区间内

            ExistsNot Exists都是根据查询语句返回true或者false!

         

         02.  例子:

    select  a.* from  A  a

     where  a.id  in(select id from B)

      如果A表中有1000条数据

           B表中有1000条数据

      分析步骤:

          01. select id from B 会查询出B表中的所有id,然后缓存起来,共1000条(因为使用in 会先执行子查询

          02.然后分别拿A表中的每一个idB表中的1000id进行比较,也就是比较了 1000*1000

          03.这样效率是非常慢的

          04.如果B表中只有100或者10条数据(只是举例说明数据量小),那么就会比较1000*10

             这样相对来说效率会高点!

     结论:

    子查询中涉及的表(B)数据量小于 主查询中涉及的表(A)数据量 时,使用In来查询!可以提高效率

    In 查询做的是 外表和内表的hash连接

    hash连接就是  以 外层查询的表作为hash table ,内层查询的表在hash table中查询数据!

     很显然,如果内层查询的数量大 ,查询效率就慢,查询数据量小,效率就高!

    03. 例子:

      select  a.* from  A  a

     where  exists  (select id from B b where a.id=b.id)

      如果A表中有1000条数据

           B表中有1000条数据

      分析步骤:

          01. 使用了exists会以外层查询为驱动)上面的sql语句只会执行1000次(因为A表中有多少条数据,就会执行几次)

          02. exists查询不需要数据的结果集,只需要返回true或者false

    结论:

    子查询中涉及的表(B)数据量大于 主查询中涉及的表(A)数据量时,使用exists来查询!可以提高效率

    Exists查询做的是loop循环

     04. 如果子查询中涉及的表(B)数据量 和 主查询中涉及的表(A)数据量 差不多时,建议使用IN来查询!

         因为In查询是在内存中的查询,exists需要查询数据库,所以内存中的查询肯定比查询数据库性能高!

     05.not exists 在任何时候都比not in 效率高!

              因为not in 那么内外表都进行全表扫描,没有用到索引not  exists的子查询仍然可以用到索引!

    any,some,all的使用

    SELECT * FROM student

    WHERE studentname

    IN(SELECT studentName FROM student)

    --  使用any(只要是在区间就行) 替换in   

    SELECT * FROM student

    WHERE studentname=ANY(SELECT studentName FROM student)

    -- all  满足子查询中编号最大的

    SELECT * FROM student WHERE

    studentNo>ALL

    (SELECT studentNo FROM student WHERE studentNo IN(1014,1001,1002))

    -- any   满足子查询中编号最小的

    SELECT * FROM student WHERE

    studentNo>ANY

    (SELECT studentNo FROM student WHERE studentNo IN(1014,1001,1002))

    --  和  any 效果一致

    SELECT * FROM student WHERE

    studentNo>SOME

    分组查询

    -- 分组  group by

    --  01. 查询 每门课程的名称 以及平均分

    --  并且按照平均分降序排列

    SELECT  subjectName,AVG(StudentResult)

    FROM  `result` r,`subject` s

    WHERE

    r.`SubjectNo`=s.`SubjectNo`

    GROUP BY subjectName

    ORDER BY AVG(StudentResult) DESC

    -- 02.在上述案例中增加   条件  having

    --  平均分>73的 显示

    SELECT  subjectName,AVG(StudentResult)

    FROM  `result` r,`subject` s

    WHERE

    r.`SubjectNo`=s.`SubjectNo`

    GROUP BY subjectName

    HAVING AVG(StudentResult)>73

    ORDER BY AVG(StudentResult) DESC

    -- 03.统计每个年级的男女人数   多列进行分组

    SELECT   gradeid '年级编号',COUNT(sex) '性别人数',sex '性别'

    FROM student

    WHERE sex IS NOT NULL AND gradeid IS NOT NULL

    GROUP BY gradeid,sex

    -- 04. 找出每个课程成绩的前三名

    SELECT * FROM result r1

    WHERE

    (

    SELECT  COUNT(1) FROM  result r2

    WHERE r1.subjectNo=r2.`SubjectNo`

    AND r1.studentresult<r2.studentresult

    )<3

    ORDER BY subjectNo,studentResult DESC

    多表连接查询

    比如之前写的小例子,查询学生的成绩,我们获取的是学生编号和成绩!

    但是如果获取了学生姓名和成绩岂不是更好? 但是学生姓名和成绩不在一张表中!

    这时候就需要我们的连接查询!

          常用的连接查询方式:

    01. 内连接

    02. 外连接

    内连接

    内连接是典型的最常用的连接查询! 特点就是两个表中存在主外健关系时,通常使用!

            查询两张表中共同的数据!

          

           内连接的实现方式有两种:

         

          01. where条件中指定连接条件

                比如 查询学生姓名以及对应的年级名称

                Select  studentName,gradeName

     from student,grade

    Where student.gradeId=grade.gradeId

          

          02.form 子句中增加 inner join  on 关系

            比如查询学生姓名,科目名称以及考试成绩

    SELECT  studentName,subjectName,studentresult

    FROM student s

    INNER JOIN result r ON s.studentNo=r.studentNo

    INNER JOIN  `subject` su ON  su.subjectNo=r.subjectNo

     注意点:

      001.inner可以省略

      002.inner join 用来连接两个表

      003.on用来设置条件

      004. s  r  su是用的别名

    外连接

    外连接查询是至少返回一个表中的所有记录,根据匹配条件有选择地返回另一张表的数据!

             外连接有主表和从表的概念!

             以主表为准匹配从表的数据,符合连接条件的数据直接返回到结果集中,不符合的数据将被赋予null之后再返回到结果集中!

                   外连接查询又分为:

    01.左外连接    Left  outer  join

    以左表为主表,从表(右边的表)中如果没有匹配的数据返回null

    例子1: 查询学生的姓名,考试科目以及成绩!

    SELECT  studentName,subjectNo,studentResult FROM  student s

    LEFT JOIN  result r  ON r.`studentNo`=s.`studentNo`

    例子2:查询所有科目对应的学生成绩

    SELECT  subjectName,s.subjectNo,studentResult FROM

    `subject`  s LEFT JOIN result r

    ON s.`SubjectNo`=r.`SubjectNo`

    02.右外连接 right outer  join

    以右表为主表,从表(左边的表)中如果没有匹配的数据返回null

      例子:查询年级名称和学生名称       两个结果是否一致?

                             SELECT gradeName,studentName FROM grade

    RIGHT JOIN student ON grade.`GradeID`=student.`GradeId`

    SELECT gradeName,studentName FROM grade

    INNER JOIN student ON grade.`GradeID`=student.`GradeId`

  • 相关阅读:
    mouse_event模拟鼠标滚轮
    润乾报表配置技术路线
    建筑 物件 开心背单词 读句子,单词,字母,看图例, 翻译,看动画
    文字过渡动画,曲线过渡动画,,使用这个插件assign shape keys
    运动锻炼 开心背单词 读句子,单词,字母,看图例, 翻译,看动画,学英语,轻松背单词,简单背单词
    blender293 内置插件 精度绘画控件,PDT学习003,pdt tangents 切线
    日常用品 背单词 读句子 看图片 读单词 读字母 翻译, 看动画 学英语
    blender293 内置插件 精度绘画控件,PDT学习 precision drawing tools
    乔布斯 背单词 02 读句子 单词 字母 翻译,看动画 学英语 名言 我菜顾我在,我菜故我在,blender加python
    狐狸 和 乌鸦 英语 朗读句子 背单词
  • 原文地址:https://www.cnblogs.com/yunfeioliver/p/9416092.html
Copyright © 2011-2022 走看看