前言
上次我们讲了数据库的基本查询,这次继续接上来数据库的高级查询。高级查询是建立在基础查询的基础上面的,如果你还没有看过建议你先去学习数据库的基础查询。
数据库的查询是数据库学习部分的重点,而数据库的高级查询是更加的重要,大家要注意多多练习,才可以更好的掌握。
建表
在基本查询中我们已经,建过表了,但是数据库的高级查询部分涉及到多个表的查询所以,我们还需要再建表,方便我们在学习过程中更好的理解记忆。
我们先建立学生表
create table t_student( id INT PRIMARY KEY NOT NULL, name VARCHAR(4) NOT NULL, age INT NOT NULL, sex CHAR(1) NOT NULL, class VARCHAR(10) , birthplace varchar(10), id_teach INT UNSIGNED NOT NULL );
#DROP TABLE t_student; INSERT INTO t_student VALUES('88201','张三',18,'男','软件211','浙江杭州',689); INSERT INTO t_student VALUES('88202','李四',19,'男','软件212','河南郑州',898); INSERT INTO t_student VALUES('88203','小红',18,'女','计算机211','北京',758); INSERT INTO t_student VALUES('88204','王五',16,'男','软件214','浙江杭州',589); INSERT INTO t_student VALUES('88205','小蓝',17,'女','计算机212','江苏常州',988); INSERT INTO t_student VALUES('88206','小王',20,'男','软件211','北京',689); INSERT INTO t_student VALUES('88207','张四',18,'男','计算机211','江苏常州',758);
输出:
建立老师表
CREATE TABLE t_teach( id INT PRIMARY KEY NOT NULL, name VARCHAR(10) NOT NULL, age INT , sex CHAR(1) , birthplace varchar(10) );
输出:
建立成绩表:
CREATE TABLE t_grade( id INT PRIMARY KEY NOT NULL, chinese INT UNSIGNED, english INT UNSIGNED, java INT UNSIGNED, python INT UNSIGNED );
输出:
建表完成,这三张表都具有一定的关联性,我们就使用这三张表来学习MySQL数据库的高级查询部分。
聚合函数
聚合函数是MySQL数据库数据处理过程中经常会用到的,求最小值、最大值、求和等。
MySQL数据库常用聚合函数详解如下:
AVG(col):返回指定列的平均值
COUNT(col):返回指定列中非NULL值的个数
MIN(col):返回指定列的最小值
MAX(col):返回指定列的最大值
SUM(col): 返回指定列的所有值之和
GROUP_CONCAT:返回由属于一组的列值连接组合而成的结果
使用格式:
SELECT COUNT(字段名) FROM 表名; SELECT MAX(字段名) FROM 表名; SELECT MIN(字段名) FROM 表名; SELECT SUM(字段名) FROM 表名;
示例:全班总分数最高的人是谁?
SELECT id,MAX(chinese+english+java+python) AS count_grade
FROM t_grade;
输出:
分组查询
GROUP BY 是分组,分组并不是去重,将查询结果按一个或多个进行分组,字段值相同的为同一组
格式如下:
SELECT 字段名1,字段名2,… FROM 表名 GROUP BY 字段1,字段2,..
GROUP BY后面的字段就是分组依据的字段,先按照字段1分组,然后按照字段二再次分组以此类推…
示例:按照班级分组
SELECT class,GROUP_CONCAT(name)
FROM t_student GROUP BY class;
输出:
Having子句
HAVING子句通常与GROUP BY子句一起使用,在SELECT语句中使用HAVING子句来指定一组行或聚合的过滤条件,以根据指定的条件过滤分组。
如果省略GROUP BY子句,则HAVING子句的行为与WHERE子句类似。但是,HAVING字句可以让我们筛选分组之后的各种数据。WHERE子句在聚合前先筛选记录,也就是说作用在GROUP BY和HAVING字句前。而HAVING子句在聚合后对组记录进行筛选。我的理解就是真实表中没有此数据,这些数据是通过一些函数产生的。
也就是说HAVING子句与WHERE子句都是可以进行条件查询的,但是WHERE子句中的条件不能包括聚合函数,但是HAVING子句可以。
这时候可能有人要说了,既然他们两个都是可以进行条件查询的,而且HAVING子句功能比WHERE子句的功能强大,那么我们为什么还要学习WHERE子句呢?
这里要注意的WHERE子句执行在SELECT子句前面,HAVING子句执行在SELECT子句的后面,如果我们使用WHERE子句的话就可以先筛选掉一大部分的数据,这要查询速度比较快,而如果只用HAVING子句那么查询速度比较慢,这样就不是一个最优的查询程序了。
使用格式如下:
SELECT 字段名1,字段名2,…
FROM 表名
GROUP BY 字段
HAVING 筛选条件;
示例:平均年龄不低于18的班级
SELECT class,GROUP_CONCAT(name) FROM t_student GROUP BY class HAVING AVG(age)>=18;
输出;
表连接查询
我们在进行数据查询时候,往往需要的数据在不同的表上,这时候我们就需要把表连接在一起来进行多表查询。表连接查询又分为:内连接查询,外连接查询,自然连接查询
接下来,我们对它们依次进行学习
内连接查询
内连接是通过在查询中设置连接条件的方式,来移除查询结果集中某些数据行后的交叉连接。简单来说,就是利用条件表达式来消除交叉连接的某些数据行。
在MySQL 的FROM 子句中使用关键字 INNER JOIN 或 JOIN 连接两张表,并使用 ON 子句来设置连接条件。内连接是系统默认的表连接,所以在 FROM 子句后可以省略 INNER 关键字,只用关键字 JOIN。使用内连接后,FROM 子句中的 ON 子句可用来设置连接表的条件。
连接格式:
SELECT 字段名1,字段名2,… FROM 表名1 JOIN 表名2... ON 连接条件;
示例:
SELECT * FROM t_student AS s JOIN t_teach AS t ON s.id_teach=t.id;
输出:
内连接还有一种隐式写法:
SELECT 字段名1,字段名2,…
FROM 表名1,表名2...
WHILE 连接条件;
效果都是一样的,不过写的时候容易忘记条件,不推荐使用这种。
外连接查询
外连接查询又分为:左连接查询与右连接查询。其中左连接查询是指以左边的表为主表,以主表的数据为基准,去匹配右边的表的数据,如果匹配到就显示,匹配不到就显示为NULL;右连接查询类似。
左外联接查询LEFT OUTER JOIN,MySQL中可以简写为LEFT JOIN;
右外联接查询RIGHT OUTER JOIN,MySQL可以简写为RIGHT JOIN;
SELECT 字段名1,字段名2,…
FROM 表名1 LEFT|RIGHT JOIN 表名2...
ON 连接条件;
示例:
SELECT * FROM t_student AS s LEFT JOIN t_teach AS t ON s.id_teach=t.id;
输出:
示例:
SELECT * FROM t_student AS s RIGHT JOIN t_teach AS t ON s.id_teach=t.id;
输出:
这里在介绍一个关键字UNION,它可以把多条SQL语句的查询结果,合并成一个结果集。如下:
SELECT * FROM t_student AS s JOIN t_teach AS t ON s.id_teach=t.id UNION SELECT * FROM t_student AS s RIGHT JOIN t_teach AS t ON s.id_teach=t.id;
输出:
自然连接查询
自连接查询就是当前表与自身的连接查询,关键点在于虚拟化出一张表给一个别名,自连接查询一般用作表中的某个字段的值是引用另一个字段的值。
示例:
SELECT t1.id,t1.java FROM t_grade AS t1 JOIN t_grade AS t2 ON t1.java=t2.java HAVING t1.java>=AVG(t2.java);
输出:
子查询
子查询允许把一个查询嵌套在另一个查询当中。子查询,又叫内部查询,相对于内部查询,包含内部查询的就称为外部查询。子查询可以包含普通SELECT可以包括的任何子句,它嵌套在一个 SELECT、SELECT…INTO 语句、INSERT…INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中。
在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。
子查询中常用的运算符
IN子查询
结合关键字 IN 所使用的子查询主要用于判断一个给定值是否存在于子查询的结果集中。其语法格式为:
<表达式> [NOT] IN <子查询>
语法说明如下。
<表达式>:用于指定表达式。当表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返FALSE;若使用关键字 NOT,则返回的值正好相反。
<子查询>:用于指定子查询。这里的子查询只能返回一列数据。对于比较复杂的查询要求,可以使用 SELECT 语句实现子查询的多层嵌套。
比较运算符子查询
比较运算符所使用的子查询主要用于对表达式的值和子查询返回的值进行比较运算。其语法格式为:
<表达式> {= | < | > | >= | <= | <=> | < > | != }
[ ALL | SOME | ANY]<子查询>
语法说明如下。
<子查询>:用于指定子查询。
<表达式>:用于指定要进行比较的表达式。
ALL、SOME 和 ANY:可选项,用于指定对比较运算的限制。
关键字 ALL 用于指定表达式需要与子查询结果集中的每个值都进行比较,当表达式与每个值都满足比较关系时,会返回 TRUE,否则返回 FALSE;
关键字 SOME 和 ANY 是同义词,表示表达式只要与子查询结果集中的某个值满足比较关系,就返回 TRUE,否则返回 FALSE。
EXIST子查询
关键字 EXIST 所使用的子查询主要用于判断子查询的结果集是否为空。其语法格式为:
EXIST <子查询>
若子查询的结果集不为空,则返回 TRUE;否则返回 FALSE。
子查询分类
子查询有以下几种:
1.标量子查询:返回单一值的标量,最简单的形式。
2.列子查询:返回的结果集是 N 行一列。
3.行子查询:返回的结果集是一行 N 列。
4.表子查询:返回的结果集是 N 行 N 列。
标量子查询:是指子查询返回的是单一值的标量,如一个数字或一个字符串,也是子查询中最简单的返回形式。 可以使用 = > < >= <= <> 这些操作符对子查询的标量结果进行比较,通常子查询的位置在比较式的右侧
MySQL 列子查询:指子查询返回的结果集是 N 行一列,由于列子查询返回的结果集是 N 行一列,因此不能直接使用 = > < >= <= <> 这些比较标量结果的操作符。在列子查询中可以使用 IN、ANY、SOME 和 ALL 操作符
MySQL 行子查询:行子查询是指子查询返回的结果集是一行 N 列,该子查询的结果通常是对表的某行数据进行查询而返回的结果集,同理不能直接使用 = > < >= <= <> 这些比较标量结果的操作符。
MySQL 表子查询:指子查询返回的结果集是 N 行 N 列的一个表数据,同理不能直接使用 = > < >= <= <> 这些比较标量结果的操作符。
示例:老师来自北京的学生有哪些?
SELECT id,name FROM t_student WHERE id_teach= (SELECT id FROM t_teach WHERE birthplace="北京");
输出:
示例:有哪些学生与老师的出生地相同?
SELECT id,name,birthplace FROM t_student WHERE birthplace = ANY (SELECT birthplace FROM t_teach);
输出:
结语
MySQL数据库这一部分我们的讲解就到此为止了,但是学习并没有结束,我们得不断地进行练习,只有这样我们在以后的工作中才能熟练的运用它们来进行办公!