#五、流程控制函数
#1. if函数:if else 的函数
SELECT IF(10 > 5, '大', '小')
#2.case函数的使用一:switch case 的效果
java中
switch(变量或表达式){
case 常量1:语句1;break;
...
default:语句n; break
}
mysql中
case 要判断的字段或表达式
when 常量1 then 要显示的值1或者语句1;
when 常量2 then 要显示的值2或者语句2;
...
else 要显示的值n或语句n;
end
#案例:查询员工的工资,要求
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
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;
#3.case 函数的使用二:类似于多重if
java中
/*
if(条件1){
语句1;
}else if(条件2) {
语句2;
}...
else{
语句n;
}
*/
mysql中:
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 条件n then 要显示的值n或语句n
#案例:查询员工的工资情况
如果工资>20000,显示A级别
如果工资>15000,显示B级别
如果工资>10000,显示C级别
否则,显示D级别
select salary,
CASE
WHEN salary > 20000 then 'A'
WHEN salary > 15000 then 'B'
WHEN salary > 10000 then 'C'
ELSE 'D'
END AS 工资级别
FROM employees
#二、分组函数
/*
功能:用作统计使用,又称为聚合函数或统计函数或组函数
分类:
sum 求和、avg 平均、max 最大值、min 最小值、count 计算个数
特点:
1、sum、avg一般用于处理数值型
max、min、count 可以处理任何类型
2、以上分组函数都忽略null值
3、可以和distinct搭配实现去重的运算
4、count函数的单独介绍
一般使用count(*)用作统计行数
5、和分组函数一同查询的字段要求是group by 后的字段
*/
#1、简单使用
select sum(salary) from employees
select count(salary) from employees
select sum(salary) 和 , count(salary) 个数 from employees
#2、参数支持哪类类型
#3、是否忽略null
select sum(commission_pct), avg(comission_pct), sum(commission_pct)/35, sum(commission_pct)/107 from employees
#4、和distinct搭配
select sum(distinct salary), sum(salary ) from employees
#5、count函数的详细介绍
select count(salary) from emplyoees
select count(*) from emplyoees //统计个数
select count(1) from emplyoees 有多少行就有多少个1
效率:
innodb存储引擎下,count(*)和count(1)的效率差不多,比count(字段)要高一些
#6、和分组函数一同查询的子弹有限制
select avg(salary), employee_id from employees;
#进阶5:分组查询
/*
select column, group_function(column)
from table
[where condition]
[group by group_by_expression]
[order by column]
select 分组函数,列(要求出现在group by的后面)
from 表
【where 筛选条件】
【group by 分组的列表】
【order by 子句】
注意:
查询列表必须特殊,要求是分组函数和group by后出现的字段
特点:
1、分组查询中的筛选条件分类两类
数据源 位置 关键字
分组前筛选 原始表 group by 字句的前面 where
分组后筛选 分组后的结果集 group by字句的后面 having
1.分组函数条件肯定是放在having子句中
2.能用分组前筛选的,就优先考虑使用分组前筛选
2、group by 子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表表达式或函数(用得较少)
3、也可以添加排序(排序放在整个分组查询的最后)
*/
#案例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
1.查询每个部门的员工个数
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的工种编号和最高工资
#1.查询每个工种有奖金的员工的最高工资
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的领导编号是哪个,以及其最低工资
1. 查询每个领导手下的最低工资
select min(salary), manager_id
from employees
group bu manager_id
2.添加筛选条件:编号>102
select min(salary), manager_id
from employees
where manager_id > 102
group bu manager_id
3.添加筛选条件最低工资>5000
select min(salary), manager_id
from employees
where manager_id > 102
group bu manager_id
having min(salary) > 5000
#按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
1.查询每个长度的员工个数
select count(*) , length(last_name) len_name
from employees
group by length(last_name)r
2.添加筛选条件
select count(*) , length(last_name) len_name
from employees
group by length(last_name)
having count(*) > 5
别名,【不通用】
select count(*) c, length(last_name) len_name
from employees
group bylen_name
having c
#按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资
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) desc
别名
select avg(salary) a, department_id, job_id
from employees
where department_id is not null
group_by department_id, job_id
having a > 10000
order by a desc
案例:查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
select min(salary), manager_id
from employees
where manager_id is not null
group by manager_id
having min(ssalary) >= 6000
#进阶6:连接查询
含义:又称多表查询、当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:
sql192标准:仅仅支持内连接
sql199标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
按功能分类:
内连接:
等值连接
非等值连接
自连接
外连接
左外连接
右外连接
全外连接
交叉连接
#一、sql192标准
#1、等值连接
-多表等值连接的结果为多表的角几部分
-n表连接,至少需要n-1个连接条件
-多表的顺序没有要求
-一般需要为表起别名
-可以搭配签名介绍的所有字句使用,比如排序、分组、筛选
#案例1:查询女神名和对应的男神名
select name, boyName form boys, beauty
where beauty.boyfriend_id = boys.id
#案例2:查询员工名和对应的部门名
select last_name, department_name
from employees,departments
where employees.department_id = departments.department_id
#2、查询员工名、工种号、工种名;为表起别名,提高语句的简洁度,区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
select last_name, e.job_id, job_title
from employees AS e, jobs j
where e.job_id = j.job_id
#3、两个表的顺序是否可以调换
select last_name, e.job_id, job_title
from jobs j, employees AS e
where e.job_id = j.job_id
#4、可以加筛选?
#案例:查询有奖金的员工名、部门名
select last_name, department_name, commission_pct I
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%'
#5、可以加分组?
#案例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 = e.department_id
AND commisson_pch IS NOT NULL
GROUP BY department_name, d.manager_id
#6、可以加排序
#案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
select job_title, count(*)
from employees e, jobs j
where e.job_id = j.job_id
GROUP BY job_title
ORDER BY count(*) DESC
#7、可以实现三表连接?
#案例:查询员工名、部门名和所在的城市
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
AND city LIKE 'S%'
ORDER BY department_name DESC
#2、非等值连接
#案例1:查询员工的工资和工资级别
select salary, grade_level
from employess e, job_grades j
where salary BETWEEN g.lowest_sal AND g.highest_sal
AND g.grade_level = 'A'
#3、自连接
#案例:查询员工名和上级的名称
select e.employee_id, e.last_name, m.employee_id, m.last_name
from employees e, employees m
where e.manager_id = m.employee_id
#二、sql99语法
/*
语法:select 查询列表
form 表1 别名 【连接类型】
join 表2 别名 on 连接条件
where 筛选条件
【group by 分组】
【having 筛选条件】
【order by 排序列表】
内连接:inner
外连接
左外:left【outer】
右外:right 【outer】
全外:full 【outer】
交叉连接:cross
*/
一:内连接
语法:
select 查询列表
from 表1 别名
inner join 表2 别名
on 连接条件
分类:
等值
非等值
自连接
特点:
-添加排序、分组、筛选
-inner 可以省略
-筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
-inner join 连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
#1、等值连接
案例1:查询员工名、部门名
select last_name, department_name
from employees e
inner join departments d
ON e.department_id = d.department_id
案例2:查询名字中包含e的员工名和工种名(筛选)
select last_name, job_title
from employees e
inner join jobs j
ON e.job_id = j.job_id
where e.last_name LIKE '%e%'
案例3:查询部门个数>3的城市名和部门个数(分组+筛选)
-查询每个城市的部门个数
-在1结果上筛选
select city, count(*) 部门个数
from departments d
inner join locations l
ON d.location_id = l.location_id
GROUP BY city
having count(*) > 3
案例4:查询哪个部门的部门员工个数>3的部门名和员工个数,并按照个数降序(排序)
-查询每个部门的员工个数
select count(*), department_name
from employees e
innet join departments d
ON e.department_id = d.department_id
GROUP BY department_name
-在1结果上筛选员工个数>3的记录,并排序
select count(*), department_name
from employees e
innet join departments d
ON e.department_id = d.department_id
GROUP BY department_name
having count(*) > 3
ORDER BY count(*) DESC
案例5:查询员工名、部门名、工种名,并按照部门名降序(添加三表连接)
select last_name, department_name, job_title
from employees e
inner join departments d ON e.department_id = d.department_id
innert join j ON e,job_id = j.job_id
ORDER BY department_name DESC
二:非等值连接
#查询员工的工资级别
select salary, grade_level
from employees e
inner join job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal
#查询工资级别的个数>2的个数,并且按工资级别降序
select count(*), grade_level
from employees e
inner join job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal
GROUP BY grade_level
having count(*) > 20
ORDER BY grade_level DESC
三:自连接
#查询员工的名字,上级的名字
select e.last_name, m.last_name
from employees e
inner join employees m
on e.manager_id = m.employee_id
where e.last_name LIKE '%k%'
二、外连接
/*
应用场景:用于查询一个表中有,另一个表没有的记录
特点:
1、外连接的查询结果为主表中的所有记录
如果从表中有和他匹配的,则显示匹配的值
如果从表中没有和他匹配的,则显示null
外连接查询结果=内连接结果+主表中有而从表没有的记录
2.左外连接, left join 左边的是主表
右外链接,right join 右边的是主表
3.左外和右外交换两个表的顺序,可以实现同样的结果
4.全外连接=内连接的结果+表1中有但表2没有的+表2中有单表1没有的
*/
#案例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
#右外
select d.*, e.employee_id
from employees e
left outer join department d
ON d.department_id = e.department_id
where e.employee_id IS NULL
#全外
select b.*, bo.*
from beauty b
full outer join boys bo
ON b.boyfiiend_id IS NULL
#交叉连接
select b.*, bo.*
from beauty b
CROSS JOIN boys bo
#sql92 和 sql99
功能:sql99支持的较多
可读性:sql99
#案例一、查询编号>3的女神的男朋友信息,如果有则列出详细,如果没有,用null填充
select b.id, b.name, bo.*
from beauty b
left outer join boys bo
ON b.boyfriend_id = bo.id
where b.id > 3
#案例二、查询哪个城市没有部门
select city, d.*
from departments d
right outer join locations l
ON d.location_id = l.location_id
where d.department_id is null
#三、查询部门名为SAL或IT的员工信息
select e.*, d.department_name
from departments d
left join employees e
ON d.department_id = e.department_id
where d.department_name IN ('SAL', 'IT')
网友评论