MySQL之DQL(二)

MySQL之DQL(二)

  • 分组查询
    • 组函数类型
      • sum 求和、avg 平均值、max 最大值 、min 最小值
      • 以上分组函数都忽略null值
      • 3、可以和distinct搭配实现去重的运算
      • 4、count函数的单独介绍
      • 效率
    • Group by子句
    • 过滤分组Having 子句
  • 多表查询
    • **1、笛卡尔集**
    • **2、等值/连接连接**
    • **3、join链接**
  • 常见函数
    • 1、字符函数
    • 2、数字函数
    • 日期函数
  • 子查询
    • 标量子查询★
    • 非法使用标量子查询
    • 列子查询(多行子查询)
    • 行子查询(结果集一行多列或多行多列)
    • select后面
    • from后面
    • exists后面(相关子查询)
  • 分页查询

接MySQL之DQL(一)的博客

分组查询

概念:

分组函数作用于一组数据,并对一组数据返回一个值。

组函数类型

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

sum 求和、avg 平均值、max 最大值 、min 最小值

sum、avg一般用于处理数值型
max、min、count可以处理任何类型

#1、简单 的使用
SELECT SUM(salary) FROM t_mysql_employees;
SELECT AVG(salary) FROM t_mysql_employees;
SELECT MIN(salary) FROM t_mysql_employees;
SELECT MAX(salary) FROM t_mysql_employees;
SELECT COUNT(salary) FROM t_mysql_employees;


SELECT SUM(salary),AVG(salary) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM t_mysql_employees;

SELECT SUM(salary),ROUND(AVG(salary),2) 平均,MAX(salary) 最高,MIN(salary) 最低,COUNT(salary) 个数
FROM t_mysql_employees;

#2、参数支持哪些类型

SELECT SUM(last_name) ,AVG(last_name) FROM t_mysql_employees;
SELECT SUM(hiredate) ,AVG(hiredate) FROM t_mysql_employees;

SELECT MAX(last_name),MIN(last_name) FROM t_mysql_employees;

SELECT MAX(hiredate),MIN(hiredate) FROM t_mysql_employees;

SELECT COUNT(commission_pct) FROM t_mysql_employees;
SELECT COUNT(last_name) FROM t_mysql_employees;

以上分组函数都忽略null值

是否忽略null

SELECT SUM(commission_pct) ,AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM t_mysql_employees;

3、可以和distinct搭配实现去重的运算

SELECT SUM(DISTINCT salary),SUM(salary) FROM t_mysql_employees;

SELECT COUNT(DISTINCT salary),COUNT(salary) FROM t_mysql_employees;

4、count函数的单独介绍

一般使用count(*)用作统计行数

SELECT COUNT(salary) FROM t_mysql_employees;

SELECT COUNT(*) FROM t_mysql_employees;

SELECT COUNT(1) FROM t_mysql_employees;

效率

MYISAM存储引擎下 ,COUNT()的效率高INNODB存储引擎下,COUNT()和COUNT(1)的效率差不多,比COUNT(字段)要高一些# 多表查询

Group by子句

和分组函数一同查询的字段必须是group by后出现的字段
筛选分为两类:分组前筛选和分组后筛选
针对的表 位置 连接的关键字
分组前筛选 原始表 group by前 where
分组后筛选 group by后的结果集 group by后 having

语法:

select 查询列表
from 表
【where 筛选条件】
group by 分组的字段
【order by 排序的字段】;

可以实现分组前的筛选

#案例1:查询邮箱中包含a字符的 每个部门的最高工资

SELECT MAX(salary),department_id
FROM t_mysql_employees
WHERE email LIKE '%a%'
GROUP BY department_id;

过滤分组Having 子句

分组后筛选

#案例:查询哪个部门的员工个数>5

#①查询每个部门的员工个数
SELECT COUNT(*),department_id
FROM t_mysql_employees
GROUP BY department_id;

#② 筛选刚才①结果

SELECT COUNT(*),department_id
FROM t_mysql_employees

GROUP BY department_id

HAVING COUNT(*)>5;

多表查询

1、笛卡尔集

笛卡尔集会在下面条件下产生

– 省略连接条件
– 连接条件无效
– 所有表中的所有行互相连接
• 为了避免笛卡尔集, 可以在 WHERE 加入有 效的连接条件。

语法:select name,boyName from beauty,boys;

2、等值/连接连接

含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询

使用连接在多个表中查询数据

• 在 WHERE 子句中写入连接条件。
• 在表中有相同列时,在列名之前加上表名前缀

等值连接
/*

① 多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③ 多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选


*/

#案例1:查询女神名和对应的男神名
SELECT NAME,boyName 
FROM boys,beauty
WHERE beauty.boyfriend_id= boys.id;

区分重复的列名

• 在不同表中具有相同列名的列可以用表的别名
加以区分。
• 如果使用了表别名,则在select语句中需要使
用表别名代替表名
• 表别名最多支持32个字符长度,但建议越少越

表的别名

• 使用别名可以简化查询。
• 使用表名前缀可以提高执行效率。

为表起别名
/*
①提高语句的简洁度
②区分多个重名的字段

注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定

*/
#查询员工名、工种号、工种名

SELECT e.last_name,e.job_id,j.job_title
FROM t_mysql_employees  e,jobs j
WHERE e.`job_id`=j.`job_id`;

连接多个表

• 连接 n个表,至少需要 n-1个连接条件。 例如:连接
三个表,至少需要两个连接条件。

可以实现三表连接

#案例:查询员工名、部门名和所在的城市

SELECT last_name,department_name,city
FROM t_mysql_employees e,t_mysql_departments d,t_mysql_locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`
AND city LIKE 's%'

ORDER BY department_name DESC;

3、join链接

– 内连接 [inner] join on
– 外连接
• 左外连接 left [outer] join on
• 右外连接 right [outer] join on

内连接
/*
语法:

select 查询列表
from 表1 别名
inner join 表2 别名
on 连接条件;
*/

SELECT last_name,department_name
FROM t_mysql_departments d
 JOIN  t_mysql_employees e
ON e.`department_id` = d.`department_id`;
外连接
 
 /*
 应用场景:用于查询一个表中有,另一个表没有的记录
 
 特点:
 1、外连接的查询结果为主表中的所有记录
	如果从表中有和它匹配的,则显示匹配的值
	如果从表中没有和它匹配的,则显示null
	外连接查询结果=内连接结果+主表中有而从表没有的记录
 2、左外连接,left join左边的是主表
    右外连接,right join右边的是主表
 3、左外和右外交换两个表的顺序,可以实现同样的效果 
 4、全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
 */
 #引入:查询男朋友 不在男神表的的女神名
 
 SELECT * FROM t_mysql_beauty;
 SELECT * FROM t_mysql_boys;
#左外连接
 SELECT b.*,bo.*
 FROM t_mysql_boys bo
 LEFT OUTER JOIN t_mysql_beauty b
 ON b.`boyfriend_id` = bo.`id`
 WHERE b.`id` IS NULL;
 
 
 #案例1:查询哪个部门没有员工
 #左外
 SELECT d.*,e.employee_id
 FROM t_mysql_departments d
 LEFT OUTER JOIN t_mysql_employees e
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;
#右外
 
  SELECT d.*,e.employee_id
 FROM t_mysql_employees e
 RIGHT OUTER JOIN t_mysql_departments d
 ON d.`department_id` = e.`department_id`
 WHERE e.`employee_id` IS NULL;
 #全外
 
 
 USE girls;
 SELECT b.*,bo.*
 FROM t_mysql_beauty b
 FULL OUTER JOIN t_mysql_boys bo
 ON b.`boyfriend_id` = bo.id;
 

 #交叉连接
 
 SELECT b.*,bo.*
 FROM t_mysql_beauty b
 CROSS JOIN boys bo;

使用ON 子句创建连接

• 自然连接中是以具有相同名字的列为连接条件的。
• 可以使用 ON 子句指定额外的连接条件。
• 这个连接条件是与其它条件分开的。
• ON 子句使语句具有更高的易读性。

常见函数

概念:类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
好处:1、隐藏了实现细节 2、提高代码的重用性
调用:select 函数名(实参列表) 【from 表】;
特点:
①叫什么(函数名)
②干什么(函数功能)

1、字符函数

作用 函数 结果
转小写 LOWER(‘SQL Course’) sql course
转大写 UPPER(‘SQL Course’) SQL COURSE
拼接 CONCAT(‘Hello’, ‘World’) HelloWorld
截取 SUBSTR(‘HelloWorld’,1,5) Hello
长度 LENGTH(‘HelloWorld’) 10
字符出现索引值 INSTR(‘HelloWorld’, ‘W’) 6
字符截取后半段 TRIM(‘H’ FROM ‘HelloWorld’) elloWorld
字符替换 REPLACE(‘abcd’,‘b’,‘m’) amcd

2、数字函数

作用 函数 结果
四舍五入 ROUND(45.926, 2) 45.93
截断 TRUNC(45.926, 2) 45.92
求余 MOD(1600, 300) 100

日期函数

作用 函数 结果
获取当前日期 now()
将日期格式的字符转换成指定格式的日期 STR_TO_DATE(‘9-13-1999’,’%m-%d-%Y’) 1999-09-13
将日期转换成字符 DATE_FORMAT(‘2018/6/6’,‘%Y年%m月%d日’) 2018年06月06日

MySQL之DQL(二)_第1张图片
案例:

#now 返回当前系统日期+时间
SELECT NOW();

#curdate 返回当前系统日期,不包含时间
SELECT CURDATE();

#curtime 返回当前时间,不包含日期
SELECT CURTIME();


#可以获取指定的部分,年、月、日、小时、分钟、秒
SELECT YEAR(NOW());
SELECT YEAR('1998-1-1');

SELECT  YEAR(hiredate) 年 FROM t_mysql_employees;

SELECT MONTH(NOW());
SELECT MONTHNAME(NOW());


#str_to_date 将字符通过指定的格式转换成日期

SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;

子查询

含义:
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询

标量子查询★



#案例1:谁的工资比 Abel 高?

#①查询Abel的工资
SELECT salary
FROM t_mysql_employees
WHERE last_name = 'Abel'

#②查询员工的信息,满足 salary>①结果
SELECT *
FROM t_mysql_employees
WHERE salary>(

	SELECT salary
	FROM t_mysql_employees
	WHERE last_name = 'Abel'

);

非法使用标量子查询


SELECT MIN(salary),department_id
FROM t_mysql_employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT  salary
	FROM t_mysql_employees
	WHERE department_id = 250
);

列子查询(多行子查询)

#案例1:返回location_id是14001700的部门中的所有员工姓名

#①查询location_id是14001700的部门编号
SELECT DISTINCT department_id
FROM t_mysql_departments
WHERE location_id IN(1400,1700)

#②查询员工姓名,要求部门号是①列表中的某一个

SELECT last_name
FROM t_mysql_employees
WHERE department_id  <>ALL(
	SELECT DISTINCT department_id
	FROM t_mysql_departments
	WHERE location_id IN(1400,1700)
);

行子查询(结果集一行多列或多行多列)

#案例:查询员工编号最小并且工资最高的员工信息
SELECT * 
FROM t_mysql_employees
WHERE (employee_id,salary)=(
	SELECT MIN(employee_id),MAX(salary)
	FROM t_mysql_employees
);

select后面

仅仅支持标量子查询

#案例:查询每个部门的员工个数
SELECT d.*,(

	SELECT COUNT(*)
	FROM t_mysql_employees e
	WHERE e.department_id = d.`department_id`
 ) 个数
 FROM t_mysql_departments d;

from后面

将子查询结果充当一张表,要求必须起别名

#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM t_mysql_employees
GROUP BY department_id


SELECT * FROM t_mysql_job_grades;


#②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal

SELECT  ag_dep.*,g.`grade_level`
FROM (
	SELECT AVG(salary) ag,department_id
	FROM t_mysql_employees
	GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

exists后面(相关子查询)

语法:
exists(完整的查询语句)
结果:
1或0

案例1:查询有员工的部门名

#exists

SELECT department_name
FROM t_mysql_departments d
WHERE EXISTS(
	SELECT *
	FROM t_mysql_employees e
	WHERE d.`department_id`=e.`department_id`


);

分页查询

应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
【join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段】
limit 【offset,】size;
offset要显示条目的起始索引(起始索引从0开始)
size 要显示的条目个数
特点:
①limit语句放在查询语句的最后
②公式
要显示的页数 page,每页的条目数size
select 查询列表
from 表
limit (page-1)*size,size;
size=10
page
1 0
2 10
3 20

案例:

案例1:查询前五条员工信息
SELECT * FROM  t_mysql_employees LIMIT 0,5;
SELECT * FROM  t_mysql_employees LIMIT 5;

案例3:有奖金的员工信息,并且工资较高的前10名显示出来
SELECT 
    * 
FROM
    t_mysql_employees 
WHERE commission_pct IS NOT NULL 
ORDER BY salary DESC 
LIMIT 10 ;

MySQL之DQL到这就结束了~~~~~~~~~
MySQL之DQL(二)_第2张图片

你可能感兴趣的:(知识梳理,代码)