进阶四:常见函数
功能:类似于java 中的方法,将一组逻辑语句分装在方法体重,对外暴露方法名
调用: select 函数名(实参列表)【from 表】
特点:
1. 叫什么(函数名)
2. 干什么(函数功能)
分类:
- 单行函数
如:concat,length,ifnull等
2.分组函数
功能:供统计使用,又称为统计函数,聚合函数,组函数等
A. 单行函数
一.字符函数
1. length :用于获取参数值的字节个数
`select length('john');
2. concat : 拼接字符串
select concat(last_name,'_',first_name) 姓名 from employees;
3. upper ,lower
select upper('john'); 变大写
select lower('JOHN'); 变小写
4. substr,substring
用于截取子字符串,注意:索引从1开始
截取从指定索引处后面所有字符
select substr('李莫愁爱上了陆展元',7) out_put
截取从指定索引处指定字符长度的字符
select substr('李莫愁爱上了陆展元',1,3) out_put
案例:姓名中首字母大写,其他字符是小写然后用_拼接,显示出来
select concat(upper(substr(last_name,1,1)),'_',lower(substr(last_name,2))) out_put from employees;
5.instr :返回子串第一次出现的索引,如果找不到就返回0
select instr('杨不悔爱上了殷六侠','殷六侠') as out_put
6. trim :去掉字符串前后空格或是指定字符或字符串
select trim(' 张翠山 ') as out_put;
select trim('a' from 'aaaa张翠山aaaaaaa') as out_put;
7. lpad :用指定的字符实现左填充指定长度
select lpad('殷素素',2,'*') as out_put;
8. rpad :用指定的字符实现右填充指定长度
select rpad('殷素素',12,'ab') as out_put;
9. replace :替换
select replace('周芷若爱上了张无忌','周芷若','赵敏');
二. 数学函数
round() :四舍五入
select round(-1.65)
select round(1.63225,4); 小数点后保留4位
ceil() :向上取整,返回>=该参数的最小整数
floor() :向下取整,返回<=该参数的最小整数
truncate() :截断
select truncate(1.699,1);
mod() :取余
select mod(10,3);
三. 日期函数
now() :返回当前系统日期+时间
select nom();
curdate() :返回当前系统日期,不包含时间
curtime() :返回当前系统时间,不包含日期
可以获取指定的部分,年,月,日,小时,分钟,秒
select year(now()) 年;
select year(hiredate) 年 from employees;
str_to_date() :将日期格式的字符转换成指定格式的日期
str_to_date('9-13-1999','%m-%d-%Y')
案例:查询入职日期为1999--2-3的员工信息
select * from emplyees where hiredate =sre_to_date('2-3 1999','%c-%d %Y');
date_format() :将日期转换为字符
select date_format(now(),'%y年%m月%d日') as out_put;
案例:查询有奖金的员工名和入职日期(xx月/xx日 xx年)
select last_name,date_format(hiredate,'%m月/%d日 %y年') 入职日期
四. 其他函数
select version()
select database();
select user();
五. 流程控制函数
1. if 函数 ,if else 的效果
select if(10<5,'大','小');
2. case 函数使用一
mysql中:
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1
...
else 要显示的值n或语句n;
案例:查询员工的工资,要求:
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
select salary 原始, department_id,
case department_id
when 30 then salary *1.1
when 40 then salary *1.2 `
3. case 函数使用二: 类似于多重if
mysql中:
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end
B. 分组函数
功能:用作统计使用,又称为聚合函数或统计函数或组函数
分类:
sum() 求和 ,avg()平均值, max() 最大值,min()最小值,count()计算个数特点:
- sum(),avg()一般用于处理数值型
max(),min(),count()可以处理任何类型- 以上分组函数都忽略null值
- 可以和distinct搭配实现去重的运算
- count函数的单独介绍
一般使用count(*)来统计行数- 和分组函数一同查询的字段要求是group by后的字段
1. 简单使用
select sum(salary) from employees;
select sum(salary) 和 ,avg(salary) 平均,max(salary) 最高 from employees;
2. 参数支持哪些类型
sum(),avg()一般用于处理数值型
max(),min(),count()可以处理任何类型
3.和distinct搭配(去重)
select sum(distinct salary),sum(salary) from employees;
4. count函数的详细介绍
select count(salary) from employees;
select count(*) from employees; 统计不为空的行数
select count(1) from employees; 统计有1 的个数
效率:
myisam存储引擎下,count()的效率高
innodb存储引擎下,count()和count(1)的效率差不多,比count(字段)要高一些
5. 和分组函数一同查询的字段有限制
select avg(salary),employees_id from employees
一般不这样写,因为avg()完成后只有一行,而employees_id有好多行,这样写在有些版本的sql软件中会报错
案例1:查询员工表中的最大入职时间和最小入职时间的相差天数(起名为diffrence)
max(hiredate) min(hiredate)
select datediff(max(hiredate),min(hiredate)) diffrence from employees;
案例2:查询部门编号为90的员工个数
select count(*) 个数 from employees where dapartment_id =90;
进阶五:分组查询
语法:
select 分组函数,列(要求出现在group by的后面)
from 表 【where 筛选条件】 group by 分组的列表
【order by 子句】
注意:
查询列表必须特殊,要求是分组函数和group by后的字段
特点:
- 分组查询中的筛选条件分为两类
分组前筛选 :数据源是原始表 ,位于group by的前面,关键字是where
分组后筛选:数据源是分组后的结果集 ,位于group by子句的后面,关键字是having
一般而言,分组函数做条件肯定是放在having 子句中
能用分组前筛选的,就优先考虑使用分组前筛选 - group by子句支持单个子段分组,多个字段分组(多个字段之间用逗号隔开)
- 也可以添加排序(排序放在整个分组查询的最后)
引入案例: 查询每个部门的平均工资
若是使用之前学的avg()直接统计,则是
select avg(salary) from employees; 但是这样算的是整体的平均,而不是每个部门的平均值
简单的分组查询
案例1:查询每个工种的最高工资
select max(salary),job_id
from employees
group by job_id;
案例2:查询每个位置上的部门个数
select count(*),location_id
from departments
group by location_id;
添加分组前的筛选条件
案例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;
添加分组后的筛选条件
案例1:查询那个部门的员工个数大于2
- 先查询每个部门的员工个数
select count(*),department_id
from employees
group by department_id;
2, 根据1中的结果进行筛选,查询哪个部门的员工个数大于2
select count(*),department_id
from employees
group by department_id
having count(*)>2;
案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
- 先查询每个工种有奖金的员工的最高工资
select max(salary),job_id
from employees
where commission_pct is not null
group by job_id
2,根据1结果继续筛选,最高工资>12000
select max(salary),job_id
from employees
where commission_pct is not null
group by job_id
having max(salary)>12000;
案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个
- 查询每个领导手下的最低工资
select min(salary) ,manager_id
from employees
group by manager_id;
2, 添加筛选条件,编号大于102
select min(salary) ,manager_id
from employees
where manager_id>102
group by manager_id;
3, 添加筛选条件,最低工资>5000
select min(salary) ,manager_id
from employees
where manager_id>102
group by manager_id
having min(salary)>5000;
按表达式或函数分组
案例1:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5有哪些
- 查询每个长度的员工个数
select count(*),length(last_name)
from employees
group by length(last_name);
2, 添加筛选条件
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 job_id,department_id
添加排序
案例:查询每个部门每个工种的员工的平均工资,并按平均工资的高低显示
select avg(salary),department_id,job_id
from employees
group by job_id,department_id
order by avg(salary) desc;
进阶六:连接查询
含义:又称为多表查询,当要查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表一有m行,表2 有n行,结果有m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:按年代分类:
sql92标准:仅仅支持内连接
sql99标准(推荐):支持内连接+外连接(左外和右外)+交叉连接按功能分类:
内连接:等值连接,非等值连接,自连接
外连接:左外连接,右外连接,全外连接
交叉连接:
一.sql92标准
A.等值连接
- 多表等值连接的结果为多表的交集部分
- n表连接,至少需要n-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`;
1.为表起别名,查询员工名,工种号,工种名
起别名可以提高语句的简洁度,区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
select e.last_name,e.job_id,j.job_title
from employees e,jobs
where employees.'job_id'=jobs.'job_id';
2.可以加筛选吗?
案例1:查询有奖金的员工名,部门名
select last_name,departmet_name,commission_pct
from employees e,departments d
where e.'department_id'=d.'department_id'
and e.'commission_pct' is not null;
案例2:查询城市名中第二个字符为o的部门
select department_name,city
from departments d,locations l
where d.'location_id'=l.'location_id'
and city like '_o%';
3. 可以加分组吗?
案例1:查询每个城市的部门个数
select count(*) 个数,city
from departments d,locations l
where d.location_id=l.location_id
group by city;
案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
select department_name,d.manager_id,MIN(salary)
from departments d,employees e
where d.department_id=e.department_id
and commission_pct is not null
group by department_name,d.manager_id;
4. 可以加排序吗?
案例1:查询每个工种的工种名和员工的个数,并且按员工个数降序
select job_title,count(*)
from employees e,jobs j
where e.job_id=j.job_id
group by job_title
order by count(*) desc;
5. 可以实现三表连接吗?
案例1:查询员工名,部门名和所在的城市
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
B.非等值连接
案例1:查询员工的工资和工资级别
select salary,grade_level
from employees e,job_grades g
where salary between g.lowest_sal and g.highest_sal;
C.自连接
自己连接自己,将同一张表看成两张表用(也就是用两次)
比如通过给定的员工名查找出员工的上级领导id,通过找出的上级领导id在
同一张表中查找出上级领导的名字(领导也属于员工,和员工数据在同一张表中)
案例1:查询 员工名和上级的名称
select e.employee_id,e.last_name,m.employee_id,m.last_name
from employees e,employees m
where e.employee_id=m.employee_id;