MySQL高级查询

1、exists和not exists子查询

/*exists的常用用法*/
drop table if exists student;

  此外,exists也可以作为where的子查询:

/*exists的参数是一个任意的子查询*/
/*若有返回行,exists的结果为true,会执行外层语句*/
/*若无返回行,exists结果为false,外层语句不再执行*/
select colums from tableName where exists(子查询);

  注意,exists和not exists的结果只取决于是否有返回记录,不取决于记录的内容。

 

  2、子查询注意事项

  (1)子查询语句可以嵌套在SQL语句中任何表达式出现的位置

  子查询可以被嵌套在select语句的列、表和查询条件中,即select子句、from子句、where子句、group by子句和having子句。

复制代码
/*select子句*/
select(子查询)from 表名;

/*from子句*/
/*这里表的别名不能省略*/
select * from(子查询 )as 表的别名;
复制代码

  (2)只出现在子查询中而没有出现在父查询中的表不能包含在输出列中;

 

  3、分组查询

  (1)group by——将查询结果按照一个、多个字段分组

/*单独使用group by*/
select * from student group by major

  当像上面那样单独使用group by时,结果中每一个不同的major只会显示一个(即每组中挑选一个显示,貌似为每组的第一个)。这样是没有太多意义的,或者说,它只显示了有多少个不同的major。

  所用我们在分组查询中会与数学统计函数结合一起使用。

  单字段分组查询:

复制代码
/*查看每门课程的平均成绩*/
select subjectNo,AVG(studentResult) as 课程平均成绩
    from result group by subjectNo;

/*查询男、女学生的人数各是多少*/
/*这里的可以这样使用*号吗?为何不直接指明列名?*/
/*可见的是表中的一行就仅代表一个人,所以这里用*表示的是对这种情况按行统计*/
select count(*) as 人数,sex from student group by sex;

/*查询每个年级的人数*/
/*这里的count(*)也是一样*/
select count(*) as 年纪人数,gradeId from student group by gradeId;

/*查询每个科目的平均分,并且按照由高到低的顺序排列显示*/
/*这里要思考的是order by的位置,注意要对哪个数据排序*/
select subjectN,AVG(studentResult) AS 平均课程成绩
   from result
   group by subjectNo;
   order by AVG(studentResult) desc;
复制代码

  多字段分组查询:

/*在一张学生信息表中有来自不同年纪、不同性别的学生,学号也都不同*/
/*现在统计每个年纪的男、女生人数*/
select count(*) as 人数,gradeId as 年级,sex as 性别 from student
    group by gradeId,sex
    order by gradeId;

  注意到了,使用group by关键字时,在select列表中可以指定的列是有限制的,仅允许group by子句后的列,聚合函数计算出的列。

 

  4、使用having子句进行分组筛选

  简单来说,having子句用来对分组后的数据进行筛选,即将组看成新的列,来进行筛选。而where子句只能对没有分组统计前的数据进行筛选。

  (1)查询年纪总人数超过1的年级——先按年级分组,再按条件筛选

select count(*) as 人数,gradeId as 年级 from student 
    group by grade
    having count(*)>2;

  (2)select语句中,where、group by、having子句和聚合函数的执行次序如下:

  where子句从数据源中去除不符合条件的数据;然后group by子句搜集数据行到各个组中;

  接着统计函数为各个组计算统计值;最后having子句去掉不符合其组搜索条件的各组数据行。

  如,查询每门课程及格总人数和及格平均分在80分以上的记录:

select count(*) as 人数,AVG(studentResult) as 平均分,subjectNo as 课程 from result
    where studentResult>=60
    group by subjectNo
    having AVG(studentResult)>=80;

 

  5、使用limit分页查询数据——基于多个表的数据查询

  (1)多表连接查询——从多个表中选择or比较数据项

    通过各个表之间共同列的关联性查询数据,是关系数据库查询最主要的特征。

  (2)内连接查询,最典型、常用的连接查询,根据表中共同的列来进行匹配。特别当两个表存在主、外键关系时通常使用内连接查询。

  (3)外连接查询,至少返回一个表中的所有记录,根据匹配条件有选择性地返回另一张表的记录。有左外连接、右外连接。

 

  6、内连接查询

  内连接通常使用“=”or“<>”等比较运算符来判断两列数据值是否相等。

  在内连接查询中,参与的表的地位是相等的。

  实现内连接的两种方式:

  (1)where子句中指定连接条件

/*查询学生姓名和成绩,成绩表中只有学号和成绩,名字在学生信息表中*/
/*from后面有两个表名*/
select student.studentName,result.subjectNo,result.studentResult
    from student,result
    where student.studentNo=result.studentNo;

  (2)在from子句中使用inner join...on

复制代码
/*inner join连接两个表,且inner可以省略*/
/*on设置条件*/
/*as指定表的别名,如果查询的列名在多个表中的名字不重复,则可以不使用表名限定*/
select S.studentName,R.subjectNo,R.studentResult
  from student as S
  inner join result as R on(S.studentNo=R.studentNo)

/*连接三个表*/
/*查询的数据分别来自三个表*/
select S.studentName as 学生姓名,SU.subjectName as 课程名称,
    R.studentResult as 考试成绩 
    from student as S
    inner join result as R on(S.studentNo=R.studentNo)
    inner join subject as SU on(SU.subjectNo=R.subjectNo)
复制代码

 

  7、外连接查询

  参与外连接查询的表有主、从之分,以主表的每行数据匹配从表的数据列,将符合连接条件的数据直接返回到结果集中;而对不符合连接条件的列,会填上null值后再返回到结果集中。(内连接中会忽略不符合条件的数据)

  (1)左外连接——left join...on,left outer join...on

  结果集包括left join中指定的左表的所有行,若左表的某行在右表中没有匹配行,则在相关的结果集行中右表的所有选择列为空值。

复制代码
/*显示所有考试名单上的学生的成绩,没有参加的也要打印出来*/
/*主表(左表)为学生信息表,学生成绩表为从表*/
/*没有参加任何科目考试的学生,在成绩表中也没有相关记录*/
/*他们对应的科目编号和成绩均会以null填充*/
select S.studentName,R.subjectNo,R.studentResult
  from student as S
  left outer join result as R on(S.studentNo=R.studentNo)
复制代码

  (2)右外连接——right outer join...on,right outer join...on

  结果集要包含右表中所有匹配的行,若右表中有的项在左表中没有对应的项,以null值填充。

  在这里,join指定的表为主表,即右表为主表。(哪个表中所有行都显示了,就是主表)

posted @ 2019-10-21 16:20  Cute_汪汪  阅读(243)  评论(0编辑  收藏  举报
Live2D