数据库的高级查询
- 聚合函数:
聚合函数在数据的查询分析中,应用十分广泛。聚合函数可以对数据求和、求最大值和最小值、平均值等。
聚合函数总共有 5 个:
SUM 函数:用于求和,只能用于数字类型,字符类型的统计结果为 0,日期类型的统计结果是毫秒数相加。
MAX 函数:用于获得非空值的最大值。
MIN 函数:用于获得非空值的最小值。
AVG 函数:用于获得非空值的平均值,非数字数据统计结果为 0。
COUNT 函数:COUNT(*) 用于获得包含空值的记录数,COUNT(字段) 用于获得包含非空值的记录数。
COUNT
是一个聚合函数,对于返回的结果集一行行地判断,如果 COUNT
函数汇总参数对应的字段值不是 Null
,累计值就加 1,否则不加,最后返回累计值。
COUNT(*)
、COUNT(1)
和 COUNT(主键id)
都返回满足条件的结果集的总行数;而 COUNT(字段)
则返回字段中值不是 Null
的总行数。
SELECT SUM(字段) FROM 数据表名称; #求和
SELECT MAX(字段) FROM 数据表名称; #求最大值
SELECT MIN(字段) FROM 数据表名称; #求最小值
SELECT AVG(字段) FROM 数据表名称; #求平均值
SELECT COUNT(*) FROM 数据表名称; #求包含空值的记录数
SELECT COUNT(字段) FROM 数据表名称; #求不包含空值的记录数
聚合函数不能出现在 WHERE
子句中。
- 分组查询:
默认情况下,聚合函数是对全表范围内的数据进行统计。
GROUP BY
子句的作用是通过一定的规则将一个数据集划分为若干个小的区域,然后针对每个小区域分别进行数据汇总处理。WHERE
子句一定要写在 GROUP BY
子句的前面。
SELECT 字段,SUM(字段) FROM 数据表名称 GROUP BY 字段; #求和
SELECT 字段,MAX(字段) FROM 数据表名称 GROUP BY 字段; #求最大值
SELECT 字段,MIN(字段) FROM 数据表名称 GROUP BY 字段; #求最小值
SELECT 字段,AVG(字段) FROM 数据表名称 GROUP BY 字段; #求平均值
SELECT 字段,COUNT(*) FROM 数据表名称 GROUP BY 字段; #求包含空值的记录数
SELECT 字段,COUNT(字段) FROM 数据表名称 GROUP BY 字段; #求不包含空值的记录数
数据库支持多列分组条件,执行的时候逐级分组。示例:
SELECT 字段1,字段2,AVG(字段3) FROM 数据表名称 GROUP BY 字段1,字段2 ORDER BY 字段1;
查询语句中如果包含 GROUP BY
子句,那么 SELECT
子句中的内容就必须要遵守规定:SELECT
子句中可以包含聚合函数,或者 GROUP BY
子句的分组列,其余内容均不可以出现在 SELECT
子句中。
对于分组的结果集,还可以使用 WITH ROLLUP
再次做汇总计算(如平均值,会再次求平均值)。示例:
SELECT 字段1,COUNT(字段2),AVG(字段3),MAX(字段4) FROM 数据表名称 GROUP BY 字段1,字段2 ORDER BY 字段1 WITH ROLLUP;
GROUP_CONCAT
函数可以把分组查询中的某个字段拼接成一个字符串。示例:
SELECT 字段1,COUNT(*),GROUP_CONCAT(字段2) FROM 数据表名称 WHERE 条件 GROUP BY 字段1;
查询语句的执行顺序:
FROM → WHERE → GROUP BY → SELECT → ORDER BY → LIMIT
HAVING
子句:
因为聚合函数不能出现在 WHERE
子句中,所以当判断条件中带有聚合函数时,WHERE
子句不能与 GROUP BY
子句一起使用,此时可以使用 HAVING
子句代替 WHERE
子句。
HAVING
子句不能单独存在,必须与 GROUP BY
子句一起使用,GROUP BY
子句执行完成后执行HAVING
子句。示例:
SELECT 字段1 FROM 数据表名称 GROUP BY 字段1 HAVING 带聚合函数的条件;
如果 GROUP BY
子句按照数字 1 分组,mysql 会依据 SELECT
子句中的第 1 列进行分组,依次类推。HAVING
子句也可以正常使用。示例:
SELECT 字段1,COUNT(*),GROUP_CONCAT(字段2) FROM 数据表名称 WHERE 条件 GROUP BY 1;
- 表的内连接:
从多张表中提取数据,必须指定关联的条件。如果不定义关联条件就会出现无条件连接,两张表的数据会交叉连接,产生笛卡尔积。
表连接分为内连接和外连接:
内连接:结果集中只保留符合连接条件的记录
外连接:不管符不符合连接条件,记录都要保留在结果集中
内连接是最常见的一种表连接,用于查询多张关系表符合连接条件的记录,通俗点理解即多张关系表符合连接条件的交集。
SELECT 字段 FROM 表1 [INNER] JOIN 表2 ON 连接条件;
SELECT 字段 FROM 表1 [INNER] JOIN 表2 WHERE 连接条件;
SELECT 字段 FROM 表1,表2 WHERE 连接条件;
内连接的数据表不一定必须有同名字段,只要字段之间符合逻辑关系即可。同一个数据表也可以做表连接。
- 表的外连接:
外连接与内连接的区别在于,除了符合条件的记录之外,结果集中还会保留不符合条件的记录。
外连接还分为左外连接和右外连接。左外连接会保留左表中的所有记录,与右表连接;右外连接则会保留右表中的所有记录,与左表连接。
SELECT 字段 FROM 表1 LEFT JOIN 表2 ON 连接条件; #左外连接
SELECT 字段 FROM 表1 RIGHT JOIN 表2 ON 连接条件; #右外连接
UNION
关键字可以将多个查询语句的结果集进行合并,合并的前提是字段个数、结果集中字段名称都要相同。示例:
(查询语句) UNION (查询语句) UNION (查询语句) ...;
使用 UNION
关键字可以将左外连接和右外连接的结果集进行合并。
此外,内连接只保留符合条件的记录,所以查询条件写在 ON
子句和 WHERE
子句的效果是相同的。但是在外连接里,条件写在 WHERE
子句里,不符合条件的记录是会被过滤掉的,而不是保留下来。
- 子查询的语法:
子查询是在查询中嵌套查询的语句,其中 SELECT
子句、FROM
子句和 WHERE
子句都可以嵌套子查询,但仅推荐在 FROM
子句中嵌套子查询。
根据不同子句中嵌套的子查询,可以分类为 SELECT
子查询、FROM
子查询和 WHERE
子查询,SELECT
子查询和 WHERE
子查询的效率都很低,FROM
子查询效率最高。
SELECT 字段1 FROM (SELECT 字段2 FROM 数据表名称) WHERE 条件;
按照结果集中的记录划分,子查询可以分为单行子查询和多行子查询。单行子查询的结果集中只有一条记录,多行子查询的结果集中有多条记录。多行子查询只能出现在 FROM
子句和 WHERE
子句中。
WHERE
子句中,可以使用 IN
、ALL
、ANY
、EXISTS
关键字来处理多行表达式结果集的条件判断。
EXISTS
关键字是把原来在子查询之外的条件判断,写到了子查询的里面。示例:
SELECT 字段1 FROM 数据表名称 WHERE [NOT] EXISTS(SELECT 字段2 FROM 数据表名称 WHERE 条件);