• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

MySQL学习笔记(四)——分组函数,分组查询,连接查询

互联网 diligentman 1周前 (11-19) 9次浏览

MySQL学习笔记(四)——分组函数,分组查询,连接查询

作者:就叫易易好了
日期:2020/11/18

一、分组函数

功能:用作统计使用,又称为聚合函数或统计函数

分类:

  • sum函数
  • avg函数
  • max函数
  • min函数
  • count函数

以下代码演示均基于myemployees数据库,可在MySQL学习笔记(一)中下载

#简单的使用案例

SELECT SUM(salary) FROM employees;
作用:求employees表中所有员工的薪水之和

SELECT avg(salary) FROM employees;
作用:求employees表中所有员工薪水的平均值

SELECT max(salary) FROM employees;
作用:求employees表中所有员工的薪水的最大值

SELECT min(salary) FROM employees;
作用:求employees表中所有员工的薪水的最小值

SELECT count(salary) FROM employees;
作用:求salary这个字段的非空值的个数

特点:

  • sum,avg一般用于处理数据类型
  • max,min,count可以处理任何类型
  • sum,avg,max,min,count都忽略null值
#与distinct函数搭配使用
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
返回值后者要比前者大很多,因为distinct是去重函数,去掉了表格里面很多重复的值
  • 对于count函数的详细介绍

SELECT (*) FROM employees;

在统计的过程中,该行只要用一个值不为null,就能统计上

此语句经常用来统计所有行数的个数,一般用这个语句统计总行数

二、分组查询

如果我们要查询employees表格中各部门的平均工资该怎么办呢?这个时候就需要使用分组查询了。

  • group by 语句

语法:

select 分组函数

from 表

where 筛选条件

group by 分组的列表

查询列表必须特殊,要求是分组函数和group by后出现的字段。

#案例:查询每个工种的最高工资
SELECT MAX(salary),jio_id
FROM employees
GROUP BY job_id
#案例:查询每个位置上的部门个数
SELECT COUNT(*),location_id
FROM departments
GROUP BY
location_id;

1、添加筛选条件

#案例1:查询邮件中包含a的字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE 
email like '%a%'
GROUP BY 
department_id;
#案例2:查询有奖金的每个领导手下员工的最高工资
SELECT 
MAX(salary),manager_id
FROM 
employees
WHERE
commission_pct  IS NOT NULL
GROUP BY 
manager_id;

2、添加复杂的筛选条件

#案例1:查询哪个部门的员工个数>2
思路:
·先查询每个部门的员工个数
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;
·根据上面的结果,出啊讯那个部门的员工个数>2
这个时候就需要有一个函数来连接上面的语句了
此时我们是用HAVING 
也就是:
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#案例2:查询每个工种有奖金的员工最高工资>12000的工种编号和最高工资
思路:先查询每个工种有奖金的员工最高工资和工种编号,
再查询最高工资大于12000的人
SELECT
MAX(salary),job_id
FROM 
employees
GROUP BY
job_id;
HAVING 
MAX(salary)>12000
#案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及最低工资
思路:查询领导编号>102的每个领导手下的领导编号,再查询最低工资大于5000的人
SELECT
MIN(salary),manager_id
FROM
employees
WHERE 
manager_id>102
GROUP BY 
manager_id
HAVING 
MIN(salary)>5000;

3、按表达式或函数分组

#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
思路:先查询每个长度的员工个数,
SELECT 
COUNT(*),
LENGTH(last_name)
FROM
employees
GROUP BY 
LENGTH(last_name)
HAVING 
COUNT(*)>5;

4、按多个字段进行分组

#案例:查询每个部门每个工种的员工的平均工资
SELECT 
AVG(salary),department_id,job_id
FROM
employees
GROUP BY 
department_id,job_id;

5、添加排序

#案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
SELECT 
AVG(salary),department_id,job_id
FROM
employees
GROUP BY 
department_id,job_id
ORDER BY
AVG(salary) DESC;

三、连接查询

也就是多表查询,当查询的数据来自于多个表的时候,就会用到连接查询

笛卡尔乘积现象:表A有m行,表B有n行,笛卡尔乘积的结果有m*n行

beauty表:

MySQL学习笔记(四)——分组函数,分组查询,连接查询

boys表:

MySQL学习笔记(四)——分组函数,分组查询,连接查询

如果执行以下语句:

SELECT name,boyname 
FROM boys,bueaty;

得到的便是:

MySQL学习笔记(四)——分组函数,分组查询,连接查询

显然……(You Know)

出现这样的原因是没有有效的连接条件,这个时候我们需要添加有效的连接条件才可以避免这种尴尬的事情发生。

分类:

  • 按年代分类

    • sq192标准:仅仅支持内连接
    • sq199标准:支持所有内连接+外连接(左外和右外)+交叉连接
  • 按功能分类

    • 内连接

      • 等值连接
      • 非等值连接
      • 自连接
    • 外连接

      • 左外连接
      • 右外连接
      • 全外连接
    • 交叉连结

1、sq192标准

1.1 等值连接

#案例1:查询女神名和对应的男神名
SELECT NAME,boyName
FROM boys,beauty
WHERE beauty.boyfriend_id=boys.id;
#案例2:查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id`=departments.`department_id`;
#案例3:为表取别名,提高语句简洁度,区分多个重名字段
  查询员工名,工种号,工种名
  SELECT last_name,e.job_id,job_title
  FROM employees AS e,jobs
  WHERE e.`job_id`=jobs.`job_id`;
  
注意:如果取了别名,查询的字段就不能使用原来的表名去限定
     FROM语句中表格的顺序可以互换
#案例4:查询有奖金的员工名,部门名
SELECT last_name,department_name,commission_pct
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct`  IS NOT NULL;
#案例5:查询城市名中第二个字符为O的部门名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND city like '_o%';

加入分组

#案例6:查询每个城市的部门个数
SELECT COUNT(*) 个数,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;

加入排序

#案例7:查询每个工种的工种名和员工个数,并且按员工个数降序排列
SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;

实现三表连接

#案例8:查询员工名,部门名和所在的城市
SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`;

1.2 非等值连接

我们先建立一个等级表:

CREATE TABLE job_grades
(grade_level VARCHAR(3),
lowest_sat INT,
highest_sal INT);

INSERT INTO job_grades
VALUES('A',1000,2999);

INSERT INTO job_grades
VALUES('B',3000,5999);

INSERT INTO job_grades
VALUES('C',6000,9999);

INSERT INTO job_grades
VALUES('D',10000,14999);

INSERT INTO job_grades
VALUES('E',15000,24999);

INSERT INTO job_grades
VALUES('F',25000,40000);

样式如下:

MySQL学习笔记(四)——分组函数,分组查询,连接查询

#案例:查询员工的工资和工资等级
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`; 

2、sql99语法

语法:

SELECT 查询列表

from 表1 别名 【连接类型】

join 表2 别名

on 连接条件

where 筛选条件

group by 分组

having 筛选条件

order by 排序列表

(提高了可读性,实现了分离)

  • 分类
    • 内连接:inner
    • 外连接
      • 左外:left [outer]
      • 右外:right[outer]
      • 全外:full [outer]
    • 交叉连接:cross

内连接

语法:

select 查询列表

from 表1 别名

inner join 表2 别名

on连接条件;

等值连接:
#案例1:查询员工名,部门名
SELECT  last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`;

添加筛选

#案例2:查询名字中包含e的员工名和工种名
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=j.`job_id`
WHERE e.`last_name` LIKE '%e%';

添加分组+筛选

#案例3:查询部门个数>3的城市名和部门个数
SELECT city,COUNT(*) 部门个数
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING count(*)>3;

添加分组+筛选+排序

#案例4:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序
SELECT COUNT(*),department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;

多表连接

#案例:查询员工名、部门名、工种名、并部门名降序排列
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d 
ON e.`department_id`=d.`department_id`
INNER JOIN jobs j 
ON e.`job_id`=j.`job_id`
ORDER BY department_name DESC;
非等值连接
#案例1:查询员工的工资级别
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON salary between g.`lowest_sal` AND g.`highest_sal`;
#案例2:查询工资级别的个数>20的个数,并且按工资级别降序
SELECT COUNT(*),grade_level
FROM employees e
INNER JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY grade_level DESC;
自连接
#案例:查询员工的名字,上级的名字
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.`manager_id`=m.`employee_id`;


喜欢 (0)