接MySQL之DQL(一)的博客
概念:
分组函数作用于一组数据,并对一组数据返回一个值。
功能:用作统计使用,又称为聚合函数或统计函数或组函数
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
SELECT SUM(commission_pct) ,AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM t_mysql_employees;
SELECT SUM(DISTINCT salary),SUM(salary) FROM t_mysql_employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM t_mysql_employees;
一般使用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前 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;
分组后筛选
#案例:查询哪个部门的员工个数>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;
笛卡尔集会在下面条件下产生
– 省略连接条件
– 连接条件无效
– 所有表中的所有行互相连接
• 为了避免笛卡尔集, 可以在 WHERE 加入有 效的连接条件。
语法:select name,boyName from beauty,boys;
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
使用连接在多个表中查询数据
• 在 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;
– 内连接 [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 表】;
特点:
①叫什么(函数名)
②干什么(函数功能)
作用 | 函数 | 结果 |
---|---|---|
转小写 | 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 |
作用 | 函数 | 结果 |
---|---|---|
四舍五入 | 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日 |
#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是1400或1700的部门中的所有员工姓名
#①查询location_id是1400或1700的部门编号
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 d.*,(
SELECT COUNT(*)
FROM t_mysql_employees e
WHERE e.department_id = d.`department_id`
) 个数
FROM t_mysql_departments d;
将子查询结果充当一张表,要求必须起别名
#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
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(完整的查询语句)
结果:
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 ;