目录
一 常见函数(单行函数)
二 分组函数
三 分组查询
四 多表连接查询
1.SQL99标准
1.1 内连接
1.2外连接
1.3交叉连接
2.子查询
3 分页查询
4 联合查询
接着上一期的数据库继续讲,上回我们说到简单的排序查询,接下来我们继续进阶,分组查询,多表连接查询。这篇博客基本都是知识点学起来比较枯燥,不过没办法为了挣钱,必须坚持下去。在学习分组查询之前不得不提到函数这个概念。因为分组查询常常是跟着分组函数联系起来的。
在常见函数里,我把它分为字符函数,数学函数,日期函数,流程控制函数,其他函数,知识点挺多的,全是干货,大家一定要仔细学习。
字符函数:
concat: 拼接
substr: 截取子串
upper: 转换成大写
lower: 转换成小写
trim: 去前后指定的空格和字符
ltrim: 去左边空格
rtrim: 去右边空格
replace: 替换
lpad: 左填充
rpad: 右填充
instr: 返回子串第一次出现的索引
length: 获取字节个数
1.length获取参数值得字节个数
SELECT LENGTH('john');
==============================================================
2.concat 拼接字符串
SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
================================================================
3.upper,lower 改变大小写
SELECT UPPER('qweA');
SELECT LOWER('GHUe');
实例:将姓变大写,名变小写,然后拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name))
FROM employees;
====================================================================
4.substr
注意:索引从一开始
截取从指定索引处开始后面所有的字符
SELECT SUBSTR('李莫愁爱上了陆展元',7);
截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了陆展元',1,3);
实例:姓名中首字母大写,其他字符小写
SELECT CONCAT( UPPER( SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)))
FROM employees;
===================================================================
5.instr 返回子串第一次出现的索引,找不到返回0
SELECT INSTR('杨不悔殷六侠爱上殷六了殷六侠','殷六侠');
===============================================================
6.trim去前后空格,不去中间
SELECT TRIM(' 张翠山 ')
SELECT TRIM('a' FROM 'aaaaaaaaaa张aaaa翠山aaaaaaa') qw
=================================================================
7.lpad 用指定字符实现左填充指定长度
SELECT LPAD('殷素素',10,'*')
SELECT LPAD('殷素素',2,'*')
=======================================================================
8.rpad 用指定字符实现右填充指定长度
SELECT RPAD('殷素素',10,'*')
SELECT RPAD('殷素素',12,'ab')
==========================================================================
9.replace
SELECT REPLACE('张无忌周芷若周若爱上了周芷若','周芷若','1' )
数学函数:
1.round 四舍五入
SELECT ROUND(1.45)
SELECT ROUND(1.456,2)
=============================
2.ceil 进一法,向上取整,>=
SELECT CEIL(1.52) 2
SELECT CEIL(-1.52) -1
=============================
3.floor 向下取整
SELECT FLOOR(-9.99) -10
SELECT FLOOR(1.52) 1
=============================
4.truncate 截断
SELECT TRUNCATE(1.65,1) 1.6
SELECT TRUNCATE(1.6999,1) 1.6
=============================
5.mod 取余
SELECT MOD(10,-3)
SELECT 10%3;
日期函数:
1.now 返回当前系统日期+时间
SELECT NOW();
2.curdate 返回当前日期
SELECT CURDATE()
3.curtime 返回当前时间
SELECT CURTIME()
4.获取指定的部分,年,月,日,小时,分钟,秒
SELECT YEAR(NOW()) 年
SELECT MONTH(NOW()) 月
5.str_to_date 字符串转日期
SELECT STR_TO_DATE('1998-3-4','%Y-%c-%d')
例子:查询入职日期为1992-4-3的员工信息
SELECT * FROM employees WHERE hiredate=STR_TO_DATE('4-3 1992','%c-%d %Y');
6.date_format 日期转字符
SELECT DATE_FORMAT(NOW(),'%Y年%m月%d日')
流程控制函数:
1.if函数:
SELECT IF('10>5','大','小');
SELECT last_name,commission_pct ,IF(commission_pct IS NULL,'没','有')
FROM employees;
2.case函数:
使用一:swith case
case 字段或表达式 when 常量 then 要显示的值或语句
案例1:
SELECT salary 原始,`department_id`,
CASE `department_id`
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE `salary`
END AS 新工资
FROM employees;
使用二:类似多重if
case when 条件 then值1 else 值 end。
SELECT `salary`,CASE
WHEN `salary`>20000 THEN 'A'
WHEN `salary`>15000 THEN 'B'
ELSE 'C'
END 工资级别
FROM employees;
其它函数:
version: 版本
database: 当前库
user: 当前连接用户
SELECT VERSION()
SELECT DATABASE()
SELECT USER()
功能:统计使用,又称为统计函数,聚合函数,组函数分类:sum 求和,avg 平均值 ,max 最大值 ,min 最小值,count 计算个数、
特点:
1.sum,AVG 一般处理数值型
max,min count 都行
2.忽略null
3.可以和distinct搭配
1.简单使用:
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
SELECT SUM(salary),COUNT(salary) FROM employees;
语法:
select 查询的字段,分组函数
from 表
group by 分组的字段
特点:
1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段
3、可以按多个字段分组,字段之间用逗号隔开
4、可以支持排序
5、having后可以支持别名
面试:
* where 和 having 的区别?
1. where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不 满足结果,则不会被查询出来
2. where 后不可以跟聚合函数,having可以进行聚合函数的判断。
例子:
1.查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),`department_id`
FROM employees
WHERE email LIKE '%a%'
GROUP BY `department_id`
案例1.查询每个工种的工资
SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;
案例2:查询每个位置上的部门个数
SELECT COUNT(*),location_id
FROM `departments`
GROUP BY `location_id`
案例3.查询哪个部门的员工个数>2
SELECT COUNT(*),`department_id`
FROM employees
GROUP BY `department_id`
HAVING COUNT(*)>2
案例4.查询每个工种有奖金的员工的最高工资>12000的员工编号,最高工资
SELECT MAX(salary),`job_id`
FROM employees
GROUP BY `job_id`
HAVING MAX(salary)>12000
案例5.查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及最低工资
SELECT MIN(salary), `manager_id`
FROM employees
WHERE `manager_id`>102
GROUP BY `manager_id`
HAVING MIN(salary)>5000
#按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
SELECT COUNT(*),LENGTH(last_name)
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(*)>5
#按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),`department_id`,`job_id`
FROM employees
GROUP BY `department_id`,`job_id`
#添加排序
#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),`department_id`,`job_id`
FROM employees
WHERE `department_id` IS NOT NULL
GROUP BY `department_id`,`job_id`
HAVING AVG(salary)>10000
ORDER BY AVG(salary)
接下来来到下一个重点:多表连接查询
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表一 m行,表二 n行 结果:m*n行
解决办法:添加连接条件
分类:
按年代分类:sql92,
sql99【推荐】
按功能分类:内连接:等值连接,非等值连接,自链接
外连接:左外连接,右外连接,全外连接
交叉连接
提到内连接,先了解了解笛卡尔集:
* 产生条件:
1. 省略连接条件
2. 连接条件无效
3. 所有表中所有行互相连接
* 解决方案:
添加有效筛选条件
语法:
select 查询列表 from 表1 别名【连接类型】
join 表2 别名
on 连接条件
【where 筛选条件】
【group by 】
【having 】
【order by】
特点:
筛选条件放在where后面,如like
分类:
内连接:inner
外连接:左外连接:left【outer】
右外连接:right【outer】
全外连接:full【outer】
交叉连接:cross
select 查询列表
from 表1 别名【inner】
join 表2 别名
on 连接条件
内连接分类:等值连接,非等值,自连接
接下来通过几个案例讲解一下:
1.等值连接
===================================================================
/*①案例1:查询员工名,部门名。*/
SELECT `last_name`,`department_name`
FROM employees e
JOIN departments d
ON e.`department_id` = d.`department_id`;
================================================================
/*②案例2:查询部门个数>3的城市名和部门个数,(添加分组,筛选)*/
SELECT `city`,COUNT(*)
FROM `locations` l
INNER JOIN `departments` d
ON l.`location_id`=d.`location_id`
GROUP BY `city`
HAVING COUNT(*)>3;
====================================================================
/*③案例3:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)*/
SELECT COUNT(*),`department_name`
FROM `departments` d
INNER JOIN `employees` e
ON d.`department_id`=e.`department_id`
GROUP BY d.`department_name`
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;
========================================================================
========================================================================
2.非等值连接
/*查询员工的工资级别*/
SELECT salary,`grade_level`
FROM `employees` e
JOIN `job_grades` g
ON e.`salary` BETWEEN g.`lowest_sal`AND g.`highest_sal` ;
===========================================================================
3.自连接
/*查询员工名,上级名*/
SELECT e.`last_name`,m.`last_name`
FROM `employees` e
JOIN employees m
ON e.`manager_id`=m.`employee_id`
这几个案例讲解的就是内连接。然后讲解外连接。
应用场景:用于查询一个表中有,宁一个表中没有的记录
特点:
1.外连接的查询结果为主表的所有记录
如果从表中有和他匹配的,则显示匹配的值
如果从表中没有和他匹配的,则显示null
2.左外连接,left左边的是主表
右外连接,right右边的是主表
还是通过一个案例,便于理解:
查询哪个部门没有员工
1.左外
SELECT d.*,e.`employee_id`
FROM `departments` d
LEFT OUTER JOIN `employees` e
ON d.`department_id`=e.`department_id`
WHERE e.`employee_id` IS NULL;
2.右外
SELECT d.*,e.`employee_id`
FROM employees e
RIGHT OUTER JOIN`departments` d
ON d.`department_id`=e.`department_id`
WHERE e.`employee_id` IS NULL;
3.全外连接
USE girls;
SELECT b.*,bo.*
FROM`beauty` b
FULL OUTER `boys` bo
ON b.`id`=bo.`id`
交叉连接
SELECT b.*,bo.*
FROM`beauty` b
CROSS JOIN boys bo
下一个重难点:子查询
含义:出现在其他语句中的select语句,称为子查询或内查询,外部的查询语句,称为主查询或外查询
分类:
1.按子查询出现的位置:
select后面 标量子查询
from后面 表子查询
※※where,having 标量子查询(单行)√ 列子查询(多行)√ 行子查询
exists(相关子查询)表子查询
2.按结果集的`department_id`行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集只有一行多列)
表子查询(结果集一般为多行多列)
特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配单行操作符
><=
列子查询,一般搭配多行操作符
in,any/some/all
4.子查询优先于主查询
1.标量子查询
/*案例一:谁的工资比abel高*/
SELECT *
FROM employees
WHERE salary >(
SELECT salary
FROM employees
WHERE last_name = 'Abel'
)
案例二:查询job——ID与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
SELECT *
FROM employees
WHERE job_id = (
SELECT job_id
FROM employees
WHERE `employee_id`=141
) AND salary>(
SELECT salary
FROM employees
WHERE `employee_id`=143
2.列子查询
案例:查询`location_id`是1400或者1700的部门中所有员工姓名
SELECT `last_name`
FROM employees
WHERE `department_id` IN(
SELECT DISTINCT `department_id`
FROM `departments`
WHERE `location_id` IN (1400,1700
)
)
查询其他部门中比job_id为‘IT_PROG’部门任一工资低的员工的,工号,姓名,job_id,salary
SELECT `employee_id`,`last_name`,`salary`
FROM employees
WHERE salary < ANY(
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
)AND job_id<>'IT_PROG'
放在exists后面(相关子查询)
语法:exists(完整查询语句)
结果0,1
SELECT EXISTS(SELECT `employee_id`FROM `employees` WHERE salary=300000)
/*查询有员工的部门名*/
SELECT `department_name`
FROM `departments` d
WHERE EXISTS (
SELECT * FROM employees e
WHERE d.`department_id`=e.`department_id`
)
语法:
select 字段|表达式,...
from 表
where 条件
group by 分组字段
having 条件
order by 排序的字段
limit 起始的条目索引,条目数;
特点:
1.起始条目索引从0开始
2.limit子句放在查询语句的最后
3.公式:select * from 表 limit (page-1)*sizePerPage,sizePerPage
假如:
每页显示条目数sizePerPage
要显示的页数 page
查询前五条
SELECT *
FROM employees
LIMIT 0,5
语法:
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
.....
select 字段|常量|表达式|函数 from 表 where 条件
特点:
1、多条查询语句的查询的列数必须是一致的
2、多条查询语句的查询的列的类型几乎相同
3、union代表去重,union all代表不去重
代码:
/*查询部门编号>90或者邮箱包含a的员工信息
*/
SELECT *
FROM employees
WHERE email LIKE'%a%'
UNION
SELECT *
FROM employees
WHERE `department_id`>90