select last_name,commission_pct,if(commission_pct isnull,'没奖金','有奖金') 备注 from employees;
#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 when30then salary*1.1 when40then salary*1.2 when50then salary*1.3 else salary endas 新工资 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或语句n; end */
/* 案例:查询员工的工资情况 如果工资>20000,显示A级别 如果工资>15000,显示B级别 如果工资>10000,显示C级别 否则,显示D级别 */ select salary, case when salary>20000then'A' when salary>15000then'B' when salary>10000then'C' else'D' endas 工资级别 from employees;
分组函数
功能
用作统计使用,又称为聚合函数或统计函数或组函数
分类
sum 求和、avg 平均值、max 最大值、min 最小值、count 计算个数
特点
sum、avg一般用于处理数值型
max、min、count可以处理任何类型
以上分组函数都忽略null值
可以和distinct搭配实现去重的运算
count函数的单独介绍
一般使用count(*)用作统计行数
和分组函数一同查询的字段要求是group by后的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#1.简单的使用 selectsum(salary) from employees; selectavg(salary) from employees; selectmax(salary) from employees; selectmin(salary) from employees; selectcount(salary) from employees;
selectsum(salary) 和,round(avg(salary),2) 平均,max(salary) 最高,min(salary) 最低,count(salary) 个数 from employees;
#3.可以和distinct搭配实现去重的运算 selectsum(distinct salary),sum(salary) from employees; selectcount(distinct salary),count(salary) from employees;
#4.count 函数的具体介绍 selectcount(salary) from employees; selectcount(*) from employees; selectcount(1) from employees;
分组查询
语法
1 2 3 4 5 6 7 8 9 10 11
/* select 分组函数,列(要求要求出现在group by 的后面) from表 [where 筛选条件] group by 分组的列表 [order by 子句] 注意:查询列表必较特殊,要求是分组函数group by 后面出现的字段 */
特点
分组查询中筛选条件分为两类
数据源
位置
关键字
分组前筛选
原始表
group by 子句的前面
where
分组后筛选
分组后的结果集
group by 子句的后面
having
①分组函数做条件肯定是放在having子句中
②能用分组前筛选的,就优先考虑分组前筛选
group by 子句支持单个字段分组,多个字段分组(多个字段用逗号隔开没有顺序),表达式或函数(用的较少)
#案例1;查询每个工种的最高工资 selectmax(salary),job_id from employees groupby job_id;
#案例2;查询每个位置上的部门个数 selectcount(*),location_id from departments groupby location_id;
#添加分组前筛选条件
#案例1;查询邮箱中包含a字符的,每个部门的平均工资 selectavg(salary),department_id from employees where email like'%a%' groupby department_id;
#案例2;查询有奖金的每个领导手下员工的最高工资 selectmax(salary),manager_id from employees where commission_pct isnotnull groupby manager_id;
#添加分组后的筛选条件
#案例1;查询哪个部门的员工个数大于2
#①查询每个部门的员工个数 selectcount(*),department_id from employees groupby department_id #②根据①的结果进行筛选,查询哪个部门员工个数大于2 selectcount(*),department_id from employees groupby department_id havingcount(*)>2;
#案例2;查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
#①查询每个工种有奖金的员工的最高工资 selectmax(salary),job_id from eemployees where commission_pct isnotnull groupby job_id;
#②根据①结果继续筛选,最高工资>12000 selectmax(salary),job_id from eemployees where commission_pct isnotnull groupby job_id havingmax(salary)>12000;
#案例3;查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
#①查询每个领导手下的员工的最低工资 selectmin(salary),manager_id from employees groupby manager_id #②添加筛选条件:编号>102 selectmin(salary),manager_id from employees where manager_id>102 groupby manager_id #③添加筛选条件:最低工资>5000 selectmin(salary),manager_id from employees where manager_id>102 groupby manager_id havingmin(salary>5000);
#按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些 #① selectcount(*),length(last_name) len_name from employees groupby length(last_name); #②添加筛选条件 selectcount(*),length(last_name) len_name from employees groupby length(last_name) havingcount(*)>5;
#按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资 selectavg(salary),department_id,job_id from employees groupby department_id,job_id;
#添加排序
#案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示 selectavg(salary),department_id,job_id from employees where department_id isnotnull groupby department_id,job_id; orderbyavg(salary) desc;
连接查询
含义
连接查询又称多表查询,当查询的字段来自多个表时,就会用到多表查询
笛卡尔积
现象:表1有m行,表2有n行,,结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类
按年代分类
sql92标准:仅仅支持内连接,也支持一部分外连接(用于oracle、sqlserver)
sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
按功能分类
内连接
等值连接
非等值连接
自连接
外连接
左外连接
右外连接
全外连接(mysql不支持)
交叉连接
一、sql92标准
等值连接
语法
1 2 3 4 5 6 7 8 9
/* select 查询列表 from 表1 别名,表2 别名 where 表1.key=表2.key [and 筛选条件] [group by 分组字段] [having 分组后的筛选] [order by 排序字段] */
#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;
#2.为表起别名 /* 提高语句的简洁度 区别多个重名的字段 注意:如果为表起了别名,则查询的字段就不能用原来的表名去限定 */ #案例:查询员工名、工种号、工种名 select last_name,e.job_id,job_title from employees e,jobs j where e.job_id=j.job_id;
#3.两个表的顺序可以调换 #案例:查询员工名、工种号、工种名 select last_name,e.job_id,job_title from jobs j,employees e where e.job_id=j.job_id;
#4.可以加筛选 #案例1:查询有奖金的员工名、部门名 select last_name,department_name,commission_pct from employees e,department d where e.department_id=d.department_id and e.commission_pct isnotnull;
#案例2:查询城市名中第二个字符为o的部门名和城市名 select department_name,city from departments d,locations l where d.location_id=l,location_id and city like'_o%';
#5.可以加分组 #案例1:查询每个城市的部门个数 selectcount(*) 个数,city from departments d,location l where d.location_id=l.location groupby city;
#案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资 select department_name,d.manager_id,min(salary) from departments d,employees e where d.department_id=e.department_id and commission isnotnull groupby department_name,d.manager_id;
#6.可以加排序 #案例:查询每个工种的工种名和员工的个数,并且按员工个数排序 select job_title,count(*) from employees e,jobs j where e.job_id=j.job_id groupby job_title orderbycount(*) 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;
非等值连接
1 2 3 4 5 6 7 8 9 10 11
#非等值连接 #案例1:查询员工的工资和工资级别 select salary,grade_level from employees e,job_grades g where salary between g.lowest_sal and g.highest_sal;
#案例2:查询工资级别为A的员工工资 select salary,grade_level from employees e,job_grades g where salary between g.lowest_sal and g.highest_sal and g.grade_level='A';
自连接
1 2 3 4
#案例:查询员工名和上级的名称 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标准
语法
1 2 3 4
select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件
内连接
语法
1 2 3 4 5 6 7 8 9
select 查询列表 from 表1 别名 innerjoin 表2 别名 on 连接条件 where 筛选条件 groupby 分组列表 having 分组后的筛选 orderby 排序列表 limit 子句
#案例1:查询员工名、部门名 select last_name,department_name from employees e innerjoin departments d on e.department_id=d.department_id;
#案例2:查询名字中包含e的员工名和工种名(添加筛选) select last_name,job_title from employees e inner joim jobs j on e.job_id=j.job_id where e.last_name like'%e%';
#案例3:查询部门个数>3的城市名和部门个数(添加分组+筛选) select city,count(*) 部门个数 from departments d innerjoin locations on d.location_id=l.location_id groupby city havingcount(*)>3;
#案例4:查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序) selectcount(*) 个数,department_name from employees e innerjoin departments d on e.department_id=d.department_id groupby department_name havingcount(*)>3 orderbycount(*) desc;
#案例5:查询员工名、部门名、工种名,并按部门名降序(三表连接) select last_name,department_name,job_title from employees e innerjoin departments d on e.department_id=d.department_id innerjoin jobs j on e.job_id=j.job_id orderby department_name desc;
#2.非等值连接
#案例1:查询员工的工资级别 select salary,grade_level from employees e innerjoin job_grades g on e.salary between g.lowest_sal and g.highest_sal;
#案例2:查询工资级别的个数>20的个数,并且按工资级别降序 select count(*),grade_level from employees e innerjoin job_grades g on e.salary between g.lowest_sal and g.highest_sal groupby grade_level havingcount(*)>20 orderby grade_level desc;
#3.自连接
#案例1:查询员工的名字,上级的名字 select e.last_name,m.last_name from employees e innerjoin employees m on e.manager_id=m.employee_id;
#案例2:查询姓名中包含字符k的员工的名字,上级的名字 select e.last_name,m.last_name from employees e innerjoin employees m on e.manager_id=m.employee_id where e.last_name like'%k%';
#①查询Abel的工资 select* from employees where last_name='Abel' #②查询员工的信息,满足salary>①结果 select* from employees where salary>( select* from employees where last_name='Abel' );
#①查询141号员工的job_id select job_id from employees where employee_id=141 #②查询143号员工的salary select salary from employees where employee_id=143 #③查询员工的姓名,job_id,和工资,要求job_id=①并且salary>② select last_name,job_id,salary from employees where job_id=( select job_id from employees where employee_id=141 )and salary>( select salary from employees where employee_id=143 );
#案例3:返回公司工资最少的员工的last_name,job_id和salary
#①查询公司的最低工资 selectmin(salary) from employees #②查询last_name,job_id和salary,要求salary=① select last_name,job_id,salary from employees where salary=( selectmin(salary) from employees );
#案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
#①查询50号部门的最低工资 selectmin(salary) from employees where department_id=50 #②查询每个部门的最低工资 selectmin(salary),department_id from employees groupby department_id #③在②基础上筛选,满足min(salary)>① selectmin(salary),department_id from employees groupby department_id havingmin(salary)>( selectmin(salary) from employees where department_id=50 );
#①查询location_id是1400或1700的部门编号 selectdistinct department_id from employees where location_id in(1400,1700) #②查询员工姓名,要求部门编号是①列表中的某一个 select last_name from employees where department_id in( selectdistinct department_id from employees where location_id in(1400,1700) );
#①查询job_id为IT-PROG部门的任一工资 selectdistinct ssalary from employees where iob_id='IT-PROG' #②查询员工号、姓名、job_id以及salary,salary<(①)的任意一个 select last_name,employee_id,job_id,salary from employees where salary<any( selectdistinct ssalary from employees where iob_id='IT_PROG' )and job_id<>'IT_PROG'; #或 select last_name,employee_id,job_id,salary from employees where salary<( selectmax (ssalary) from employees where iob_id='IT_PROG' )and job_id<>'IT_PROG';
#案例3:返回其他工种中比job_id为IT-PROG工种所有工资都低的员工的员工号、姓名、job_id以及salary select last_name,employee_id,job_id,salary from employees where salary<all( selectdistinct ssalary from employees where iob_id='IT_PROG' )and job_id<>'IT_PROG'; #或 select last_name,employee_id,job_id,salary from employees where salary<( selectmin (ssalary) from employees where iob_id='IT_PROG' )and job_id<>'IT_PROG';
select* from employees where (employee_id,salary)=( selectmin(employee_id),max(salary) from employees ); #—————————————————————————————————————————— #①查询最小的员工编号 selectmin(employee_id) from employees #②查询最高工资 selectmax(salary) from employess #③查询员工信息 select* from employess where employee_id=( selectmin(employee_id) from employees )and salary=( selectmax(salary) from employess );
二、select 后面
select 后面仅仅支持标量子查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#案例1:查询每个部门的员工个数 select d.*,( selectcount(*) from employees e where e.department_id=d.department_id )个数 from departments d;
#案例2:查询员工号=102的部门名 select ( select department_name from departments d innerjoin employees e on d.department_id=e.department_id where e.employee_id=102 ) 部门名;
三、from后面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资 selectavg(salary),department_id from employees groupby department_id #②连接①的结果集和job_grades表,筛选条件平均工资between lowest_sal and highest_sal select ag_dep.*,g.grade_level from ( selectavg(salary) ag,department_id from employees groupby department_id ) ag_dep innerjoin job_grades g on ag_dep.ag between lowest_sal and highest_sal;
四、exists后面
语法:exists(完整的查询语句)
结果:1或0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#案例1:查询有员工的部门名 select department_name from departments d whereexists( select* from employees e where d.department_id=e.department_id );
#使用in select department_name from departments d where d.department_id in( select department_id from employees );
分页查询
应用场景
当要显示的数据,一页显示不全,需要分页提交sql请求
特点
limit 语句放在查询语句的最后
公式
1 2 3 4
#要显示的页数page,每页的条目数size select 查询列表 from 表 limit (page—1)*size,size;
语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
select 查询列表 from 表 [ jion type join 表2 on 连接条件 where 筛选条件 groupby 分组字段 having 分组后的筛选 orderby 排序的字段 ] limit [offest,]size;
#1.查询姓名中包含a字符的员工名、部门名和工种信息 #①创建 createview myv1 as select last_name,department_name,job_title from employees e join departments d on e.department_id=d.department_id join jobs j on j.job_id=e.job_id; #②使用 select*from myv1 where last_name like'&a&';