前言
今天为大家分享的是DQL数据查询语言的后续部分知识点,
上一篇博客已经分享了DQL数据查询语言的概念、特点、
基本的SELECT语句、过滤和排序数据以及分组查询!
DQL前文:DQL数据查询语言前文部分
分组查询
(一)、过滤分组Having 子句
1、语法: select 查询列表 from 表 【where 筛选条件】 group by 分组的字段 【order by 排序的字段】;
2、特点:
1、和分组函数一同查询的字段必须是group by后出现的字段
2、筛选分为两类:分组前筛选和分组后筛选
分组前筛选 | 分组后筛选 |
---|---|
针对的是原始表 | 针对的是group by后的结果集 |
where关键字 | having关键字 |
3、分组前筛选:
案例1:查询邮箱中包含a字符的 每个部门的最高工资
SELECT MAX(salary),department_id
FROM t_mysql_employees
WHERE email LIKE '%a%'
GROUP BY department_id;
结果:
案例2:延伸案例1,得出以下结论!
SELECT MAX(salary),manager_id,department_id
FROM t_mysql_employees
WHERE email LIKE '%a%'
GROUP BY department_id;
结论:虽然可以查询出结果,但是结果不一定正确,因为一个部门里面不可能只有一个员工,所以说最好按照查询出来的列名进行分组!
分组后筛选:
案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT job_id,MAX(salary)
FROM t_mysql_employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;
结果:
(二)、where条件筛选和having条件筛选的区别以及应用场景:
例1:查询员工数大于5的部门
SELECT COUNT(*),department_id
FROM t_mysql_employees
WHERE salary>12000
GROUP BY department_id;
例2:查询员工数大于5的部门
SELECT COUNT(*),department_id
FROM t_mysql_employees
GROUP BY department_id
HAVING salary>12000;
结果如下:
结论:虽然两种方式的最终运行结果是一样的,但是其实内在的使用逻辑不一样,where关键字是先进行条件的判断,再筛选;反之,having关键字是先进行筛选,再进行判断的,只是由于表的设计,所以运行结果一样,并不是说两者之间没有区别,所以容易混淆!
注意:having后带的条件必须是整个sql语句中select查询出来的列!
案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
首先分析题中的条件:
1、每个工种 意思是按照工种分组 group by job_id
2、有奖金 意思是奖金率不为空 使用where条件
3、最高工资>12000 意思是分组后筛选 使用having关键字
SELECT job_id,MAX(salary)
FROM t_mysql_employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;
结论:当我们看到这样的sql语句时,要学会分析条件!
4、添加排序
案例:每个工种有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序
SELECT job_id,MAX(salary) m
FROM t_mysql_employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING m>6000
ORDER BY m ;
这里也需要案例题目中的条件!
5、按照多个字段分组
案例:查询每个工种每个部门的最低工资,并按最低工资降序
SELECT MIN(salary),job_id,department_id
FROM t_mysql_employees
GROUP BY department_id,job_id
ORDER BY MIN(salary) DESC;
多表查询
1、原因:为了避免笛卡尔集,可以在 WHERE 加入有效的连接条件
2、笛卡尔集:
2.1、省略连接条件
2.2、 连接条件无效
2.3、所有表中的所有行可以互相连接
3、笛卡尔集只是一种组合方式而已!
案例:查询出女生名对应的男生名字
SELECT NAME,boyName
FROM t_mysql_boys,t_mysql_beauty
WHERE beauty.boyfriend_id= boys.id;
一、等值连接
特点:
1、多表等值连接的结果为多表的交集部分
2、表连接,至少需要n-1个连接条件
3、表的顺序没有要求
4、般需要为表起别名
5、以搭配前面介绍的所有子句使用,比如排序、分组、筛选
1、给表格起别名
目的:1、提高语句的简洁度 2、区分多个重名的字段
案例:查询员工名、工种号、工种名
SELECT e.last_name,e.job_id,j.job_title
FROM t_mysql_employees e,jobs j
WHERE e.`job_id`=j.`job_id`;
2、调换两个表格之间的顺序
案例:查询员工名、工种号、工种名
SELECT e.last_name,e.job_id,j.job_title
FROM t_mysql_jobs j,t_mysql_employees e
WHERE e.`job_id`=j.`job_id`;
3、可以加筛选
案例:查询有奖金的员工名、部门名
SELECT last_name,department_name,commission_pct
FROM t_mysql_employees e,t_mysql_departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;
4、可以加分组
案例1:查询每个城市的部门个数
SELECT COUNT(*) 个数,city
FROM t_mysql_departments d,t_mysql_locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;
5、可以加排序
案例2:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT job_title,COUNT(*)
FROM t_mysql_employees e,t_mysql_jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;
6、可以三表连接
案例:查询员工名、部门名、工种名,并按部门名降序
SELECT last_name,department_name,job_title
FROM t_mysql_employees e
INNER JOIN t_mysql_departments d ON
e.`department_id`=d.`department_id`
INNER JOIN t_mysql_jobs j ON e.`job_id` = j.`job_id`
ORDER BY department_name DESC;
7、自连接
案例:查询员工的名字、上级的名字
SELECT e.last_name,m.last_name
FROM t_mysql_employees e
JOIN t_mysql_employees m
ON e.`manager_id`= m.`employee_id`;
二、外连接
1、应用场景:用于查询一个表中有,另一个表没有的记录;
2、几种连接类型的特点:
连接类型 | 特点 |
---|---|
外连接 | 外连接的查询结果为主表中的所有记录 |
左外连接 | 左外连接,left join左边的是主表 |
右外连接 | 右外连接,right join右边的是主表 |
左外连接:
案例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;
1、全外连接=内连接的结果+表1中有 但表2没有的+表2中有 但表1没有 2、左外连接和右外连接即使交换两个表的顺序,也能实现同样的效果! 3、如果从表中有和它匹配的,则显示匹配的值 如果从表中没有和它匹配的,则显示null 外连接查询结果=内连接结果+主表中有而从表没有的记录
常见函数
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 |
注意:mysql本身是不区分大小写的,但是为了实现DBA(数据工程师)的一些需求,我们可以使用函数进行大小写之间的转换!
案例1:大小写转换
SELECT UPPER('john');
SELECT LOWER('joHn');
案例2:将姓变大写,名变小写,然后拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name))
姓名 FROM t_mysql_employees;
2、数字函数
作用 | 函数 | 结果 |
---|---|---|
四舍五入 | ROUND(45.926, 2) | 45.93 |
截断 | TRUNC(45.926, 2) | 45.92 |
求余 | MOD(1600, 300) | 100 |
案例1:四舍五入
SELECT ROUND(-1.55);
SELECT ROUND(1.567,2);
四舍五入的数字函数会使用得较多!
3、日期函数
作用 | 函数 | 结果 |
---|---|---|
获取当前日期 | now() | 当前时间 |
字符转换成指定格式的日期 | STR_TO_DATE(‘9-13-1999’,’%m-%d-%Y’) | 1999-09-13 |
将日期转换成字符 | DATE_FORMAT(‘2018/6/6’,‘%Y年%m月%d日’) | 2018年06月06日 |
字符转日期和日期转字符这两种日期函数在很多大型公司中会使用得较多,其中m表示的是月份,d表示的是日,Y表示的是年份!
分页查询
1、应用场景:
当要显示的数据,一页显示不全,需要分页提交sql请求;
2、语法:
select 查询列表 from 表 【join type join 表2 on 连接条件 where 筛选条件 group by 分组字段 having 分组后的筛选 order by 排序的字段】 limit 【offset,】size;
offset要显示条目的起始索引(起始索引从0开始)
size 要显示的条目个数
案例1:查询前五条员工信息
SELECT * FROM t_mysql_employees LIMIT 0,5;
SELECT * FROM t_mysql_employees LIMIT 5;
案例2:查询第11条——第25条
SELECT * FROM t_mysql_employees LIMIT 10,15;
案例3:有奖金的员工信息,并且工资较高的前10名显示出来
SELECT
*
FROM
t_mysql_employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10 ;
子查询
1、含义
出现在其他语句中的select语句,称为子查询或内查询,
外部的查询语句,称为主查询或外查询
2、按照子查询出现的位置:
位置 | 作用 |
---|---|
select后面 | 仅仅支持标量子查询 |
from后面 | 支持表子查询 |
where或having后面 | 标量子查询(单行) 列子查询 (多行) 行子查询 |
exists后面 | (相关子查询) 表子查询 |
3、案例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'
);
总结
今天的博客就分享到这啦,注意书写sql语句前分析,学会分析也很重要,遇到错误不要慌,一步一步地进行分析,说不定就能得出结果啦,欢迎评论区留言交流,告辞!