聚合函数
聚合函数在数据的查询分析中,应用十分广泛。聚合函数可以对数据求和、最大值和最小值、求平均值 等等。
# 求公司员工的平均月收入:
SELECT AVG(sal+IFNULL(comm,0)) AS avg FROM t_temp;
# sal和comm是列名。 AVG求平均值聚合函数。
# IFNULL(comm,0),如果comm的值为null,则赋值0
SUM函数
SUM函数用于求和,只能用于数字类型,字符类的统计结果为0,日期类型统计结果是毫秒数相加。
SELECT SUM(ename) FROM t_emp;
# ename 列名
SELECT SUM(sal) FROM t_emp WHERE deptno IN(10,20);
# sal,deptno列名 t_emp表
# deptno IN(10,20) deptno的值在(10,20)里面就匹配
MAX函数
MAX函数用于获得非空值的最大值。
SELECT MAX(comm) FROM t_emp;
# 查询员工名字最长的是几个字符:
SELECT MAX(LENGTH(ename)) FROM t_emp;
# LENGTH() --统计字符个数
MIX函数
MIN函数用于获得非空值的最小值。
SELECT MIN(empno) FROM t_emp;
AVG函数
AVG函数用于获得非空值的平均值,非数字数据统计结果为0
COUNT函数
COUNT(*)用于获得包含空值的记录数,COUNT(列名)用于获得包含非空值的记录数。
SELECT COUNT(*) FROM t_emp;
# 查询所有的记录,包含空值
SELECT COUNT(comm) FROM t_emp;
# 查询佣金表数据,不统计空值
分组查询
为什么要分组?
默认情况下汇总函数是对全表范围内的数据做统计。
GROUP BY 子句的作用是通过一定规则将一个数据集划分成若干个小的区域,然后针对每个小区域分别进行数据汇总处理。
SELECT deptno,AVG(sal) FROM t_emp GROUP BY deptno;
# GROUP BY deptno; deptno是员工部门,里面包含10,20,30部门,GROUP BY就把他们10,20,30分别分成一个组
# 然后deptno,AVG(sal) 显示部门编号和每个部门的平均薪水。
# ROUND(AVG(sal)) --》 把小数转换成整数。
逐级分组
- 数据库支持多列分组条件,执行的时候逐级分组。
- 查询每个部门里,每种职位的人员数量和平均底薪
SELECT deptno,job,COUNT(*),AVG(sal) FROM t_emp GROUP BY deptno,job ORDER BY deptno;
# GROUP BY deptno,job 先按照部门分组,再对职位进行分组
# ORDER BY deptno; 根据部门进行排序
对SELECT子句的要求
查询语句中如果含有GROUP BY子句,那么SELECT子句中的内容就必须要遵守规定:SELECT子句中可以包括聚合函数,或者GROUP BY子句的分组列,其余内容均不可以出现在SELECT子句中。
SELECT deptno,AVG(sal),SUM(sal),MAX(SAL),MIN(sal),COUNT(*) FROM t_emp GROUP BY deptno WITH ROLLUP;
# WITH ROLLUP 对汇总的结果再次汇总计算
GROUP_CONCAT函数
GROUP_CONCAT函数可以把分组查询中的某个字段拼接成一个字符串,返回一条记录。
# 查询每个部门内底薪超过2000元的人数和员工姓名
SELECT deptno,GROUP_CONCAT(ename),COUNT(*) FROM t_emp WHERE sal>=2000 GROUP BY deptno;
查询语句中,各种子句的执行顺序
FROM->WHERE->GROUP BY->SELECT->ORDER BY->LIMIT
HAVING子句
HAVING子句跟在GROUP BY 子句后面,用作条件判断,类似WHERE.但是WHERE不能够对聚合函数进行筛选,HAVING不能单独使用,必须跟在GROUP BY后面
SELECT deptno FROM t_emp GROUP BY deptno HAVING AVG(sal)>=2000;
# 查询每个部门中,1982年一会入职的员工超过2个人的部门编号
SELECT deptno FROM t_emp
WHERE hiredate>="1982-01-01"
GROUP BY deptno HAVING COUNT(*)>=2;
ORDER BY deptno ASC;
HAVING子句的特殊用法
按照数字1分组,MySQL会依据SELECT子句中的列进行分组,HAVING子句也可以正常使用。
SELECT deptno,COUNT(*) FROM t_emp GROUP BY 1;
SELECT deptno,COUNT(*) FROM t_emp GROUP BY 1 HAVING deptno IN (10,20);
# 如果过滤的数据量比较大,能够使用WHERE过滤的尽量先使用WHERE对数据进行过滤
表连接查询
从多张表中提取数据
从多张表中提取数据,必须制定关联的条件。如果不定义关联条件就会出现无条件连接,两张表的数据会交叉连接,产生笛卡尔积。
# 错误的例子
SELECT empno,ename,dname FROM t_emp JOIN t_dept;
# 规定了连接条件的表连接语句,就不会出现笛卡尔积
SELECT e.empno,e.ename,d.dname FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno;
# ON子句是做筛选用的,作用与WHERE是相同的
表连接的分类
- 表连接分为两种:内连接和外连接
- 内连接是结果集中只保留符合连接条件的记录
- 外连接是不管符不符合连接条件,记录都要保留在结果集中
内连接的简介
内连接 最常见的一种表连接,用于查询多张关系表符合连接条件的记录。
SECT ... FROM 表1
[INNER] JOIN 表2 ON 连接条件
[INNER] JOIN 表3 ON 连接条件;
# 语法二:
SELECT ... FROM 表1 JOIN 表2 WHERE 连接条件;
# 语法三:
SELECT ... FROM 表1,表2 WHERE 连接条件;
# 查询每个员工的工号、姓名、部门名称、底薪、职位、工资等级
SELECT e.empno,e.ename,d.deptno,e.sal,e.job,s.grade FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal
# 内连接的数据表不一定必须有同名字段,只要字段之间符合逻辑关系就可以。
# 查询与SCOTT相同部门的员工都有谁
SELECT e2.ename FROM t_emp e1 JOIN t_emp e2 ON e1.deptno=e2.deptno WHERE e1.name="SCOTT" AND e2.ename!="SCOTT";
# 相同的数据表也可以做表连接
# 查询底薪超过公司平均底薪的员工信息
SELECT e.empno,e.ename,e.sal
FROM t_emp e JOIN
(SELECT AVG(sal) avg FROM t_emp) t
ON e.sal>=t.avg;
# SELECT的查询结果可以作为一个表连接
# 查询RESEARCH部门的人数、最高底薪、最低底薪、平均底薪、平均工龄
# FLOOR()--取整,去掉小数位
# CELL()--取整,有小数位就进1,不管小数位是多少
SELECT COUNT(*),MAX(e.sal),MIN(e.sal),AVG(e.sal),
FLOOR(AVG(DATEDIFF(NOW(),e.hiredate)/365)) FROM t_emp e JOIN t_dept d ON e.deptno=d.deplno WHERE d.name="RESEARCH";
表的外连接
外连接与内连接的区别
外连接与内连接的区别在于,除了符合条件的记录之外,结果集中还会保留不符合条件的记录。
SELECT e.empno,e.ename,d.dname
FROM
t_emp e
LEFT JOIN t_dept d ON e.deptno=d.deptno;
# LEFT JOIN 左外连接关键字
# RIGHT JOIN 右外连接关键字
(查询语句) UNION (查询语句) #
左连接和右连接
左外连接 就是保留左表所有的记录,与右表做连接。如果右表有符合条件的记录就与左边连接。如果右表没有符合条件的记录,就用NULL与左表连接。右连接也是如此。
子查询
子查询是一种查询中嵌套查询的语句
注意:不推荐在WHERE语句中使用子查询,应当用表内连接查询
子查询可以写在三个地方:WHERE子句、FROM子句、SELECT子句,但是最有FROM子句子查询是最可取的。
单行子查询和多行子查询
- 单行子查询的结果集中只有一条记录,多行子查询结果集有多行记录
- 多行子查询只能出现在WHERE子句和FROM子句中
|