注意:这里面很有可能一些图片的结果与sql语句不一致,是因为上传时,出现了错误,并不是sql语句本身的错误!!!
myemployees.sql和girls.sql链接为:链接:
https://pan.baidu.com/s/1AcFDFdhxHMuugaiqePXQHg
提取码:izvp
提取码:izvp
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
mysql基础
1.将myemployees数据库导入Linux上的mysql
点击右键---》执行SQL脚本--->选择电脑中存储myemployees数据的地方
---加入成功
2.使用数据库的好处:
1.实现数据的持久化
2.使用完整的管理系统统一管理数据,易于查询
3.DB,DBMS,SQL
DB:数据库(database),用于保存一组有组织的数据容器
DBMS:数据库管理系统(DataBase Management System),又称数据库软件,用于管理DB中的数据
SQL:结构化查询语言(Structure Query Language),用于和DBMS进行通信
4.数据库的特点
1.将数据放入表中,再将表放入库中 (数据---->表---->库)
2.一个数据库可以有多个表(表名具有唯一性)
3.表具有一些特性,定义了数据在表中怎样存储,类似于Java中的"类"
4.表包含多列,每一列也称为字段,每一列代表一个属性,类似于Java中的"属性"
5.数据在表中按每行进行存储,类似于Java中的“对象”
5.DBMS分为两种:
1.基于共享文件系统
2.基于客户端--服务器的DBMS
6.在服务端进行启动
1.[root@test~】# msyql -u root -p
entrning password: root---因为密码设置为"root"
2.使用某一个数据库----如:myemployees
mysql > use myemployees;
3.查看表
mysql > show tables;
4.查看版本号
mysql > select mysql();
7.mysql的语言规范
1.不区分大小写,但建议关键字大写,表名和列名小写
2.每条命令以分号结束
3.每条命令可以根据需要进行缩进
4.注释:
1.单行: #或者--
2.多行:/*....*/
8.DQL,DML,DDL,TCL
1.DQL:数据查询语言
2.DML:数据操作语言
3.DDL:数据定义语言
4.TCL:事务控制语言
9.DQL
进阶1:基础查询
语法:select 查询列表 from 表名;----类似于Java中System.out.pritnln("dfjfkj");
查询列表:字段,常量值,表达式,函数
查询出来的是一个虚拟表
案例:
1.查询表中的某一个字段---如:employees表中的last_name;
mysql > select last_name from employees;
2.查看表中的多个字段---如:employees中的first_name和last_name
mysql> select first_name,last_name from employees;
3.查看表中的所有字段
mysql > select * from employees;
4.查看常量值----注意:字符型和日期型需要使用双引号引起来,数值型不需要
mysql > select 100;
5.查看表达式----注意:不支持自增和自减
mysql > 100*100;
6.查看函数---注意:1.必须有select 2.必须有返回值
mysql > select concat(first_name,last_name) from employees;---concat:将两个字段进行拼接
1.帮查询字段起别名
1.使用as
mysql > selsect last_name as 姓,first_name as 名 from employees;----as后面跟着别名
2.使用空格
mysql > select last_name 姓,first_name 名 from employees;-----使用空格代替as,然后后面跟着别名
注意:
起别名尽量不要起中间有空格的名字,比如out put
如果起了,解决方法:out put上面打双引号 "out put"
2.去重---distinct
案例:查询员工表中涉及到的所有部门编号
mysql > SELECT DISTINCT(department_id) FROM employees;
mysql > select distinct dartment_id from employees;----也可以这样写(建议这样写)
注意:
1.只能返回它的目标字段,而无法返回其他字段
案例:
mysql > select distinct department_id, department_name from deprtments;----可以去重
mysql > select distinct department_id,distinct department_name from departments;-----报错
2.必须放在要查询字段的开头
3.所以一般用来查询不重复记录的条数-----count(distinct department_id)
3."+"
1.java中的"+"
a.当左右为数值型----加法
b.当左右有一边为字符串-----连接
2.mysql中的“+”----只做运算符
1.两边为数值型----加法
2.一边为字符串
a.如果字符串可以转换为数值型---加法
b.如果字符串不能转换为数值型---将其设为0,再做加法
3.左右两边有一边为Null,则不管另一边为什么,返回的都是null
案例:
mysql > SELECT "dfsjf" + "eir";
4.concat----字符串的链接
mysql > select concat(first_name,last_name) from employees;
5.ifnull(表达式1,表达式2)----到表达式1为Null时,使用表达式2代替
案例:----employees表中没有奖学金的用“没有奖学金”代替
mysql > SELECT DISTINCT(IFNULL(commission_pct,"没有奖学金")) AS 奖学金 FROM employees;
6.isnull(表达式)----判断表达式是否为空,如果是则返回1,否则返回0
案例:
mysql > select last_name,commission_pct ,isnull(commission_pct) 奖金情况 from employees;
进阶2:条件查询
语法:select 查询列表 from 表名 where 筛选条件
执行顺序:from---> where---->select
分类:
1.按条件表达式查询----“< > 不等于(<>),等于(=),>=,<=”
案例:查询工资 > 12000的员工姓名
mysql > SELECT CONCAT(first_name,last_name) 姓名 FROM employees WHERE salary > 12000;
2.按逻辑表达式筛选---用于谅解表达式-----"&&(and),||(or),!(not)"
案例:查询工资在10000到20000至今的员工名,工资以及奖金
mysql > select last_name 姓名,salary 工资,commission_pct 奖金 from employees where salary > 10000 and salary < 20000;
-----有14行数字,没有全部列举出
3.模糊查询
1.like:一般和通配符“%和_”一起使用,%表示任意多个字符,_表示任意一个单字符
2.between and
3.in
4.is null 或is not null
like:
案例:查询员工名中包含字符a的员工信息
mysql >select * from employees where concat(first_name,last_name) like "%a%";------从这里可以看出,函数可以使用在where的后面
案例:查询员工名中第二个字符为_的员工信息
mysql > select * from employees where concat(first_name,last_name) like "_\_%";-----当查询的是_,需要进行转义"或者使用下面:
mysql > select * from employees where concat(first_name,last_name) like "_a_%" escape 'a';-----这里的a表示转义字符,这里的a可以是b,c,d,.....任意字符
between and:
案例:查询员工编号在100到120之间的员工信息
mysql > select * from employees where employee_id between 100 and 120;
1.使用between and 可以提高语言的简洁度
2.包括临界值
3.两个临界值不能调换顺序
in:
案例:查询员工工种编号IT_PROG,AD_VP,AD_PRES中的一个员工名和工种编号
mysql > select last_name,job_id from employees where job_id in('IT_PROG','AD_VP','AD_PRES');
1.使用in提高语句的简洁读
2.in中的列表中的值必须一致或者兼容
is null 或is not null:
案例:查询没有奖学金的员工名和奖金
mysql > select last_name, commission_pct from employees where commission_pct is null;
注意:
完全等于<=>
1.is null:仅仅可以判断null值,可读性高,建议使用
2.<=>:即可以判断null的值,又可以判断普通的值,可读性低
案例:
mysql > select last_name,commission_pct from employees where commission_pct <=> null;
mysql > select last_name,salary from employees where salary <=> 12000;
进阶3:排序查询
1.语法:
select 查询列表 from 表名 【where 筛选条件】order by [asc(升序,默认),desc(降序)]
2.执行顺序:from ---->where-----> select----->order by
案例:按年薪的高低显示员工的信息和年薪
mysql > SELECT *,salary * 12 *(1 + IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 DESC;
----别名也可以用在order by中,条件语句中不可以使用别名
案例:按姓名的长度显示员工的姓名和工资
mysql > select length(concat(first_name,last_name)) 姓名,salary as 工资 from employees order by 姓名 asc;
3.总结:
1.order by字句汇中可以支持单个字段,多个字段,表达式,函数,别名
2.order by字句一般放置在查询语句的最后,limit字句除外
案例:
1.查询员工的姓名和部门编号和年薪,按年薪降序,按姓名升序
mysql > select concat(first_name,last_name) 姓名,salary * 12 * (1 + ifnull(commission_pct,0)) as 年薪,department_id 部门编号 from employees order by 年薪 asc,姓名 desc;
2.选择工资不在8000到12000的员工的姓名和工资,按工资降序
mysql > select concat(first_name,last_name) 姓名,salary 工资 from employees where salary between 8000 and 12000 order by salary desc;
3.查询邮箱中包含e的员工信息,并选择邮箱的字节降序,再按部门编号升序
mysql > select * from employees where email like '%e%' order by length(email) desc,department_id asc;
进阶4:常函数----类似于Java中的方法,将一组逻辑语句封装到方法体中,对外暴露方法名
1.好处:隐藏实现细节 ,提高代码的重用性
2.语法:select 函数(参数列表) [from 表名]
3.分类:
1.单行字符:
1.字符函数
1.length----计算字符的字节长度
案例:员工表中员工姓名的长度
msql > select concat(first_name,last_name) as 姓名, length(concat(first_name,last_name)) 名字的长度 from employees;
----一个字符占一个长度
案例:
mysql > select length("张三丰hahahhaha");
----一个汉字占三个字节
2.concat---拼接,上面案例
3.upper,lower----字符全转大写,全转小写
案例:将员工表中的姓名全传大写,全转小写
mysql > select upper(concat(first_name,last_name)) 姓名 from employees;
mysql > select lower(concat(first_name,last_name)) 姓名 from employees;
4.substr,substring----截取,mysql中索引都是从1开始
案例:
mysql > select substr("李莫愁爱上了陆展元",7);
mysql > select substr("李莫愁爱上了陆展元",1,3);
-----包含1,3指的是长度
mysql > select substring("李莫愁爱上了陆展元",7);
mysql > select substring("李莫愁爱上了陆展元",1,3);
5.instr---返回子字符串第一次出现索引,如果没有则返回0
案例:
mysql > select instr("杨不悔爱上了殷六侠","殷六侠");
6.trim--去掉首尾的空格或者指定字符
案例:
msyql > select trim(" 赵翠三 adjfkfjk ");
案例:
msyql > select trim('a' from "aaaaaaaaaaaaaaaa张aaaaaaaaaaaaaaaa翠aaaaaaaaa山aaaaaaaaaaa") as output ;
7.lpad---使用指定的字符左填充指定长度
案例:
mysql > select lpad("殷素素“,10,"*");----字符串小于10个字符时,左边使用“*"来填充
mysql > select lpad('殷素素',2,'*');-------当指定长度小于原有的字符串长度时,截取原有的字符串长度
8.rpad-----用指定的字符右填充指定长度
案例:
msyql > SELECT RPAD('殷素素',10,'你是一个笨蛋淡淡的');
9.replace----使用指定字符来替代字符串中的字符串或者字符串本身
案例:
mysql > select replace('张无忌爱上了周芷若','周芷若','赵敏');
-----使用赵敏来替代周芷若
2.数学函数
1.round---四舍五入
案例:
mysql > select round(1.65);
mysql > select round(-1.65);
mysql > select round(1.45678,3);-----3表示保留几位小数
2.ceil----向上取整(返回>=该参数的最小整数)
案例:
mysql > select ceil(1.002);
mysql > select ceil(-1.02);
3.floor---向下取整(返回<=该数的最大整数)
案例:
mysql > select floor(-9.99);
4.truncate---截取----不四舍五入
案例:
mysql > select truncate(1.68888,3);----3表示小数点保留3位,不四舍五入
mysql > select truncate(666666666,3);
---对整数不起作用
5.mod(a,b)---取余----(a-a/b*b)---a为负数,则结果为负数,a为正数,则结果为正数
案例:
mysql > select mod(-10,-3);------(-10-(-10/-3)*(-3)) = -10 - 3*(-3) = -1
3.日期函数
1.now()---表示返回当前日期,时间
案例:
mysql > select now();
2.curdate----显示当前的日期,不包括时间
案例:
mysql > select curdate();
3.curtime---显示时间,不包括日期
案例:
mysql > select curtime();
4.获得指定部分---year(),month(),monthname(),day(),hour(),minute(),second()
案例:
mysql > select year(hiredate) 入职年份 from employees;
案例:
mysql > select month(now());
mysql > select day("2020-9-24");
5.str_to_date----将字符通过指定的格式转换成日期
案例:查询入职日期为1992-4-2的员工的姓名,月薪
mysql > select concat(first_name,last_name) 姓名,salary 月薪 from employees where hiredate = str_to_date('4-3-1992','%c-%d-%Y');
6.date_formate----将日期转换为字符串
案例:查询有奖金的员工的姓名和入职日期(xx月/xx日/xx年
mysql > select concat(first_name,last_name) 姓名,date_format(hiredate,"%m/%d/%y") as 入职日期 from employees where commission_pct is not null;
注意:
%Y---四位数的年份
%y---2位数的年份
%m--月份(01,02,....12)
%c---月份(1,2,3,4....12)
%d---日
%H---小时(24小时制)
%h---小时(12小时制)
%i----分钟
%s----秒
7.日期函数-----datediff(表达式1,表达式2)----返回表达式1-表达式2的值
案例:查询员工表中最大的入职时间和最小的入职时间的相差天数
mysql > select max(hiredate) 最晚的入职时间, min(hiredate) 最早的入职时间,datediff(max(hiredate),min(hiredate)) 相差天数 from employees;
4.其他函数
version(),database()---查看当前的库,user()------查看当前的用户
5.流程控制函数
1.if(表达式1,表达式2,表达式3)函数-------相当于Java中的三元运算符,表达式1为真,则返回表达式2,否则返回表达式3
案例:
mysql > select concat(first_name,last_name) 姓名,commission_pct 奖金, if(commission_pct,"有奖金","没奖金") 奖金情况 from employees;
----commission_pct为null时,表示为假,返回表达式3
2.case函数
1.语法:-----相当于Java中的switch case的效果
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
.......
else 要显示的值n或语句n;
end
注意:
1.上面黄色的部分:
1.如果case放置在select的后面使用,相当于一个表达式,那么黄色的部分就不能是一个表达式了, 只能是一个值,并且没有分号";"
2.如果case放置在存储过程就可以将其当做语句使用,可以不搭配select使用,这是黄色部分放的是语句,需要加上分号";"
案例:
部门号 = 30,显示工资为1.1倍
部门号 = 40,显示工资为1.2倍
部门号 = 50,显示工资为1.3倍
其他 原工资
显示这些员工的姓名,原工资,上涨的工资
mysql > select concat(first_name,last_name) 姓名,department_id 部门号,salary 原工资,
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;
2. 语法:-----类似于Java中的多重if
case
when 条件1 then 要显示的值1或语句1;
when 条件2 then 要显示的值2或语句2;
.........
else 要显示的值n或语句n;
end
案例:
部门员工的工作情况:
如果工资 > 20000,显示A
如果工资 > 15000显示B
如果工资 > 10000显示C
其他 显示D
mysql > select concat(first_name,last_name) 姓名,salary 工资,
case
when salary > 20000 then 'A'
when salary between 15000 and 20000 then 'B'
when salary between 10000 and 15000 then 'C'
else 'D'
end
as 工资级别
from employees;
2.分组函数
1.功能:用作统计使用,又称为聚合函数或统计函数或组函数
2.分类:
sum--求和,avg---平均,max---最大值,min---最小值,count---计算个数
3.简单使用:
mysql > select sum(salary) 总工资,avg(salary) 平均工资,max(salary) 最大的工资,min(salary) 最小的工资,count(salary) 员工个数 from employees;
4.参数类型支持哪些类型
1.sum,avg只支持数值类型
2.max,min,count支持任意类型
5.是否忽略null
sum,avg,max,min,count都忽略null,count计算的是非空个数
6.可以和distinct搭配使用起到去重计算的效果
mysql > select sum(distinct salary) from employees;
----与上面的总工资相比,达到了去重的效果
7.count函数的详细介绍
1. mysql > select count(commisssion_pct) from employees;
2.mysql > select count(*) from employees;
3.mysql > select count(1) from employees;
总结:
1).1中的结果与2,3的结果不一样,因为1中会忽略null
2).count(*)中的“*”表示任意字段,在每一行中,如果有一个字段不为Null,那就代表这一行不为null,要计1行
3).count(1)这相当于在表中增加了一个虚拟字段,其值都为1,所以其结果与count(salary)一样(这是因为salary中没有null)
4)效率:在mysam存储引擎中,count(*)效率最高,在innodb存储引擎中,count(*)和count(10的效率差不多,比count(字段)要高一些
8.和分组函数一同查询的字段有限制-----要求是group by后的字段
mysql > select avg(salary),employee_id from employees;-------avg(salary)一行,employee_id为107行
进阶5:分组
1.group by---将表中的所有数据按照要求分成若干个组
2.语法:
select 查询列表------【分组函数,列(出现在grop by的后面)】
from 表名
[where 筛选条件]
group by 分组的列名
[order by 子句]
注意:查询列表特殊,要求是分组函数和group by后出现的字段
案例:
1.查询每个工种的最高工资
mysql > select max(salary) 最高工资,job_id as 工种编号 from employees group by job_id;
2.查询每个位置上的部门个数
mysql > select count(*) 部门个数,loacation_id as 位置号 from departments group by location_id;
3.添加筛选条件----分组前,使用where
案例:查询邮箱中包含a字符的每个部门的平均工资
msyql > select avg(salary) 平均工资,department_id 部门编号 from employees where email like '%a%' group by department_id;
查询有奖金的每个领导手下员工的最高工资
mysql > select max(salary) 最高工资,manager_id 领导编号 from employees where commission_pct is not null group by manager_id;
4.添加复杂的筛选条件---分组后,使用having
案例:查询那个部门的员工个数>2
mysql > select department_id 部门编号,count(*) 员工个数 from employees group by department_id having count(*) > 2;
查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
mysql > select job_id 工种编号,max(salary) 最高工资 from employees where commission_pct is not null group by job_id having max(salary) > 12000;
查询领导编号>102的每个领导手下的最低工资>5000的领导编号以及最低工资
mysql > select manager_id 领导编号,min(salary) 最低工资 from employees where manager_id > 102 group by manager_id having min(salary) > 5000;
比较:
分组查询中的筛选条件分为两种情况:
数据源 位置 关键字
分组前筛选 原始表 group by 字句之前 where
分组后筛选 分组后的结果集 group by 字句之后 having
1.分组函数做条件肯定是放在having子句中
2.分组前筛选的,就优先考虑使用分组前筛选
3.where子句作用于表和视图,having子句作用于组
4.where在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算),而having在分组和聚集之后选取分组的行。因此,where子句不能包含聚集函数;因为试图用聚集函数判断那些行输入给聚集运算时没有意义的。想反,having子句总是包含聚集函数(严格来说,可以不使用聚集的having子句,但这样做是没有意义的,同样的条件可以更有效的用于where阶段)
5.having一般跟在group by之后,执行记录组选择的一部分来工作的,where则是执行所有数据来工作的,再者having可以用来聚合函数
5.按表达式或函数分组
案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
mysql > select count(*) 员工个数,length(concat(first_name,last_name)) 姓名长度 from employees group by length(concat(first_name,last_name)) having count(*) > 5;
6.按多个字段分组----逗号隔开
案例:查询每个部门每个工种的员工的平均工资
mysql > select avg(salary) 平均工资,department_id 部门编号,job_id 工种编号 from employees group by department_id,job_id ;
7.添加排序
案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
msyql > select avg(salary) 平均工资,department_id 部门编号,job_id 工种编号 from employees group by department_id,job_id order by 平均工资 desc;
总结:
1.group by子句支持单个字段分组,多个字段分组(多个字段之间使用逗号隔开,没有顺序要求),表达式或函数
2.也可以添加排序(排序放在整个分组查询的最后)
案例:查询各job_id的员工工资的最大值,最小值,平均值,总和,并按Job_id升序
mysql > select job_id 工种编号 max(salary) 最高工资,min(salary) 最小工资,avg(salary) as 平均工资,sum(salary) 总和 from employees group by job_id order by job_id asc;
案例:查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
mysql > select min(salary) 最低工资,manager_id 领导编号 from employees where manager_id is not null group by manager_id having 最低工资 > 6000;
案例:查询所有部门的编号,员工数量,工资平均值,并按平均工资降序
mysql > select count(*) 员工个数,avg(salary) 平均工资,department_id 部门编号 from employees group by department_id order by 平均工资 desc;
进阶6:连接查询
1.含义:又称为多表查询,当查询的字段不在同一个表时,就会用到连接查询
2.笛卡尔积现象:表1有m行,表2有n行,结果为m*n行
3.发生原因:没有有效的连接条件
4.如何避免:添加有效的连接条件
5.分类:
1.sql92标准----只支持内连接
2.sql99标准----支持内连接,外连接,交互连接
6.按功能分为:
内连接:等值连接,非等值连接,自连接
外连接:左外连接,右外连接,全外连接(mysql不支持)
交互连接
sql92标准
1.等值连接
案例:查询女神和对应的男神名
mysql > use girls;
mysql > SELECT beauty.name 女神名,boyName 男神名 FROM beauty ,boys WHERE beauty.`boyfriend_id` = boys.id;
-----使用的是表名.字段
2.为表起别名----与字段起别名一样,两种方法,好处为:提高语句的简洁度,区分重名字段
案例:查询员工名,工种名,工种号
mysql > use myemployees;
mysql > SELECT CONCAT(first_name,last_name) 员工姓名,e.job_id 工种号,job_title 工种名 FROM employees e,jobs j WHERE e.`job_id` = j.`job_id`;
---两个好处都体现了,在该案例中
注意:
1.字段e.job_id这里如果表已经起了别名,就不能再使用beauty.boy_id,因为在执行一条sql语句时,总是从from表名开始的
2.在where中不能使用别名,在group by ,order by中可以使用别名
3.两个表之间的顺序是任意的
4.可以筛选
案例:查询有奖金的员工名,部门名
mysql > select concat(first_name,last_name) 员工名,department_name 部门名 from employees as e,departments as d where e.department_id = d.department_id and commission_pct is not null;
案例:查询城市名中第二个字符为o的部门名和城市名
msyql > select department_name 部门名,city 城市名 from departments d,locations l where d.location_id = l.location_id and city like '_o%';
5.可以加分组
案例:查询每个城市的部门个数
mysql > select count(d.department_id) 部门个数,city 城市名 from locations l,departments d where d.location_id = l.location_id group by city;
---count(department_id)可以使用count(*)来代替
案例:查询有奖金的某个部门的部门名和部门的领导编号和该部门的最低工资
mysql > select min(salary) 最低工资,department_name 部门名,manager_id 领导编号 from employees e,departments d
where d.department_id = e.department_id and commission_pct is not null group d.department_id;
6.可以加排序
案例: 查询每个工种的工种名和员工个数,并且按员工个数降序
mysql > select j.job_title as 工种名, count(*) 员工个数 from employees as e,jobs j where e.job_id = j.job_id group by j.job_id order by count(*) desc;
7.多表链接
案例:查询员工名,部门名,所在的城市
mysql > select concat(first_name,last_name) as 员工名,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.n表连接,需要n-1个连接条件
3.多表没有顺序要求
4.一般需要为各个表起别名
5.可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
2.非等值连接-----除了不为“=”,都为非等值
案例:查询员工的工资和工资级别
mysql > select salary 工资,grade_level 工资级别 from employees,job_grades where salary between lowest_sal and highest_sal;
3.自连接
案例:查询员工名和上级名称
mysql > select concat(e1.first_name,e1.last_name) 员工名,concat(e2.first_name,e2.last_name) 上级名 from employees e1,employees e2 where e1.manager_id = e2.employee_id;
sql 99:
1. 内连接:等值,非等值,自连接
2.外连接:左外连接,右外连接,完全连接(mysql不支持)
3.交互连接
1.等值连接-----与sql 92标准一样
语法:select 查询列表 from 表1 [as] 别名, 表2 [as] 别名 where 表1的别名.key = 表2的别名.key [and 筛选条件] [group by 分组条件] [ having 分组后的筛选条件] [ order by 排序实现]
特点:
1.一般为表起别名
2.多表的顺序可以调换
3.n个表连接需要n-1个条件
4.等值连接为多表的交集部分
2.非等值连接----上面的where中的“=”换成“非=”
3.自连接
案例:
1.显示所有员工的姓名,部门名和部门号
mysql > select concat(first_name,last_name) 员工姓名,department_name 部门名, d.department_id 部门号 from employees e,departments d where e.department_id = d.department_id;
2.查询90号部门员工的job_id和90号部门的location_id
mysql > select job_id 工种号, location_id 区域编号 from employees e,departments d where e.department_id = d.department_id and d.department_id = 90;
3.选择所有有奖金的员工的last_name,department_name,location_id,city
mysql > select last_name 姓名,d.department_name 部门名,l.location_id 区域号,city 城市名 from employees e,departments d,locations l where e.department_id = d.department_id and d.location_id = l.location_id and commission_pct is not null;
4.选择city在Toronto工作的员工的last_name,job_id department_id ,department_name
mysql > select last_name 姓名,job_id 工种号,d.department_id 部门编号,department_name 部门名 from employees e,departments d,locations l where e.department_id = d.department_id and d.location_id = l.location_id and city = 'Toronto';
5.查询每个工种,每个部门的部门名,工种名和最低工资
mysql > select department_name 部门名,job_title 工种名, min(salary) 最低工资 from employees e,departments d,jobs j where e.department_id = d.department_id and e.job_id = j.job_id group by j.job_id,d.department_id;
6.查询每个国家下个部门个数大于2的国家编号
mysql > select count(*) 部门个数,country_id 国家编号 from departments d,locations l where d.location_id = l.location_id group by country_id having count(*) > 2;
7.选择指定员工的姓名,员工号以及他的管理者的姓名和员工号,结果类似于下面的格式
employees Emp# manager mgr#
kochhar 101 King 100
mysql > select e1.last_name 员工姓名,e1.employee_id 员工号,e2.last_name 管理者姓名,e2.employee_id 管理者编号 from employees e1,employees e2 wherw e1.manager_id = e2.employee_id and e1.last_name = 'kochhar';
SQL99
1.语法:
select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件 [where 筛选条件] [ group by 分组] [having 筛选条件] [ order by 排序列表]
2.连接类型
1.内连接 inner
2.外连接
左外(left [outer]) 右外(right [outer])全外(full [outer])
3.交互连接 cross
3.内连接
1.语法:
select 查询列表 from 表1 别名 inner join on 连接条件 ......
2.等值
分类:
1.等值
案例:查询员工名,部门名
mysql > select concat(first_name,last_name) 员工姓名,department_name 部门名 from employees e inner join departments d on e.department_id = d.department_id;
案例:查询名称中包含e的员工名和工种名---添加条件
mysql > select concat(first_name,last_name) 员工名,job_title 工种名 from employees e inner join jobs j on e.job_id = j.job_id where concat(first_name,last_name) like '%e%';
案例:查询部门个数 > 3的城市名和部门个数---添加分组+筛选
mysql > select count(*) 部门个数,city 城市名 from departments d inner join locations l on d.location_id = l.location_id group by city having count(*) > 3;
案例:查询那个部门的员工个数 > 3的部门名和员工个数,并按个数降序---添加排序
mysql > select count(*) 员工个数, department_name 部门名 from employees e inner join departments d on e.department_id = d.department_id group by department_name having 员工个数 > 3 order by 员工个数 desc;
案例:查询员工名,部门名,工种名,并按部门名降序----多表联合查询
mysql > select concat(last_name,first_name) 员工名,department_name 部门名,job_title 工种名 from employees e inner join departments d inner join jobs j on e.department_id = d.department_id and e.job_id = j.job_id order by department_name desc;
这个案例这样做是错的
mysql > select concat(last_name,first_name) 员工名,department_name 部门名,job_title 工种名 from employees e
inner join departments d on e.department_id = d.department_id
ininer jobs j on e.job_id = j.job_id order by department_name desc;
先蓝色部分得到交集,再用这交集的部分与红色的部分进行交集,得到结果
特点:
1.可以添加排序,分组,筛选
2.inner可以省略
3.筛选条件咋where之后,连接条件在on之后,提高了代码的复用性,用于阅读
4.inner join连接和sql92语法中的等值效果是一样的,都是查询交集
2.非等值连接
案例:查询员工的工资级别
mysql > select concat(first_name,last_name) 员工姓名,salary 工资,grade_level as 员工的工资级别 from employees e inner join job_grades on salary between lowest_sal and highest_sal;
案例:查询工资级别的个数大于20,并且按工资级别降序
mysql > select count(*) 个数 from employees inner join job_grades on salary between lowest_sal and highest_sal group by grade_level having count(*) > 20 order by grade_level;
3.自连接
案例:查询员工名,上级的名字
mysql > select concat(e1.first_name,e2.last_name) 员工名字,concat(e2.first_name,e2.last_name) 上级名字 from employees e1 inner join employees e2 on e1.manager_id = e2.employee_id;
4.外连接
引入:查询没有男朋友的女神名
应用场景:用于查询一个表中有,另一个表中没有的记录
特点:
1.外连接的查询结果为主表中所有的记录
1.如果从表中有和它匹配的,则显示匹配的值
2.如果从表中没有和它匹配的,则显示null
3.外连接查询的结果 = 内连接结果 + 主表中有而从表中没有的记录
2.左外---左边的表是主表,右外---右边的表示主表,即要查询的信息来自哪个表,那个表就是主表
3.左外和右外交换两个表的顺序,可以实现同样的效果
案例;查询男朋友不在男神表中的女神名
mysql > use girls;
msyql > SELECT b.name 女神名,bo.boyName FROM beauty b LEFT JOIN boys bo ON b.`boyfriend_id` = bo.`id` WHERE bo.`id` IS NULL;
总结:
案例:查询哪个部门没有员工
mysql >select count(*) 员工个数,department_id 部门编号 from employees group by department_id having count(*) = 0;---
完全错误,完全不理解题意
mysql > select d.department_id 部门编号,employee_id 员工编号 from departments d left join employees e on d.department_id = e.department_id where employee_id is null;
5.全外连接
全外连接 = 内连接的结果 + 表1中有但表2中没有 + 表1中没有但表2中有
6.交叉连接--笛卡尔积
A = {1,2}
B = {a,b,c}
A * B = {(1,a),(1,b),(1,c),(2,a),(2,b),(2,c)}
案例
1.查询编号 > 3的女神名的男朋友的信息,如果有则列出详细,如果没有,则null填充
mysql > use grils;
mysql > select b.name 女神姓名, bo.* from beauty b left join boys bo on b.boyfriend_id = bo.id where b.id > 3;
1.查询哪个城市没有部门
mysql > select city 城市,department_name 部门名 from departments d right join locations l on d.location_id = l.location_id where d.department_id is null;
3.查询部门名为SAL或IT的员工信息
mysql >select department_name 部门名,e.* from departments d left join employees e on d.department_id = e.department_id where department_name in ('SAL','IT');