MySQL安装
MySQL密码修改
mysqladmin -u用户名 -旧密码 password 新密码
MySQL服务登录和退出
mysql -u root -p
quit;
MySQL常见的命令
查看版本
进入mysql
mysql -u root -p
select version();
退出mysql
mysqld --version
查询表格
show databases; //查看数据库所有的表
use [表名]; //打开某个表
show tables; //查看该表的详情
show tables from [库名]; //查看某个表的详情
select database(); //查看当前进入的是哪个库/哪张表
desc [表名]; //查看表结构
MySQL的语法规范
- 不区分大小写,但建议关键字大写,表名、列名小写
- 每条命令最好用分号结尾
- 每条命令根据需要可以进行缩进或者换行
- 注释
单行注释 #注释文字 ; – 注释文字
多行注释 /* 注释文字 */
DQL语言
data query language:数据查询语言,主要涉及到select语句
进阶一:基础查询
语法:select 查询列表 from 表名
特点:
1、查询列表可以是:表中的字段、常量值、表达式、函数等
2、查询的结果是一个虚拟的表格
use myemployees;
1、查询表中的单个字段
select last_name from employee;
2、查询表中的多个字段
select last_name,salay,email from employee;
3、查询表中的所有字段
select * from employee; #顺序与原表一致
4、查询常量值
select 100;
select 'john';
5、查询表达式
select 100*98;
6、查询函数
select version();
7、起别名
①便于理解
②如果要查询的字段有重名的情况,可以使用别名来区分开来
#方式一:as 结果
select 100%98 as 结果;
select last_name as 姓,first_name as 名 from employees;
#方式二:使用空格
select last_name 姓,first_name 名 from employees;
8、去重
select distinct department_id from employees;
9、+号的作用
mysql中+号有且只有一个作用,那就是运算符
select 100+90; 两个操作数都为数值型,则做加法运算
select ‘123’+90; 其中一方为字符型,试图将字符型数值转换成数值型如果转换成功,则继续做加法运算
select ‘john’+90; 如果转换失败,则将字符型数值转换成0
select null+10; 只要其中一方为null,则结果肯定为null
select concat(first_name,last_name) as 姓名 from employees;
select concat(last_name,',',first_name,',',id) as output from employees;
10、查看表结构
desc 表名;
案例:
select IFNULL(commission_pct,0) as 结果,commission_pct from employees;
select concat(first_name,',',last_name,',',ifnull(commission_pct,0)) as 姓名 from employees;
进阶2:条件查询
语法:
select
查询列表 第三步
from
表名 第一步
where
筛选列表 第二步
分类:
一、按条件表达式筛选
条件运算符: > < = != >= <=
二、按逻辑表达式筛选
逻辑运算符:
作用:用于连接条件表达式
&& || !
and or not
&&和and:两个条件都为TRUE,结果为TRUE,反之为FALSE
||和or:只要有一个条件为TRUE,结果为TRUE,反之为FALSE
!和not:条件为FALSE,结果为TRUE;条件为TRUE,结果为FALSE
三、模糊查询
like
between and
in
is null
#一、按条件表达式筛选
#查询薪资大于12000的员工信息
select * from employees where salary>12000;
#查询部门编号不等于90号的员工名和部门编号
SELECT first_name,department_id FROM employees WHERE department_id!=90;
#二、按逻辑表达式筛选
#查询工资在10000到20000之间的员工名、工资及奖金
SELECT first_name,salary,commission_pct FROM employees WHERE salary>=10000 AND salary<=20000;
#查询部门编号不是在90-100之间,或者工资高于15000的员工信息
SELECT * FROM employees WHERE department_id<90 or department_id>110 or salary>15000;
SELECT * FROM employees WHERE !(department_id>=90 and department_id<=110) or salary>15000;
#三、模糊查询
#like\between and\in\is null\is not null
#1、like
#特点:①一般和通配符搭配使用
# 通配符:
# % 任意多个字符,包含0个字符
# _ 任意单个字符
#案例一:查询员工名称中包含字符a的员工信息
SELECT * FROM employees WHERE first_name LIKE '%t%';
#案例二:查询员工名称中第三个字符为n,第五个字符为l的员工名和工资
SELECT first_name,salary FROM employees WHERE last_name LIKE "__n_l%";
#案例二:查询员工名称中第二个字符为_l的员工名和工资
SELECT first_name,salary FROM employees WHERE last_name LIKE "_\_%";
SELECT last_name,salary FROM employees WHERE last_name LIKE "_$_%" escape '$';
#2、between and
#特点: ①使用between and可以提高语句的简洁度
# ②包含临界值
# ③两个临界值不要调换顺序
#案例一:查询员工编号在100-120之间的员工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
#3、in
#含义:判断某字段的值是否属于in列表中的某一项
#特点: ①使用in提高语句建解读
# ②in列表的值类型必须一致或兼容
# ③不能使用通配符
#案例一:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT
first_name 员工名,job_id 工种,manager_id 工种编号
FROM
employees
WHERE
job_id in ('IT_PROG','AD_VP','AD_PRES');
#4、is null
#含义:判断某字段的值是否为空
# 不为空 is not null
#案例一:查询没有奖金的员工名和奖金率
SELECT
first_name 员工名,commission_pct 奖金率
FROM
employees
WHERE
commission_pct is null;
#安全等于<=>
#案例一:查询没有奖金的员工名和奖金率
SELECT
first_name 员工名,commission_pct 奖金率
FROM
employees
WHERE
commission_pct <=> null;
#案例二:查询奖金为12000的员工名和奖金率
SELECT
first_name 员工名,commission_pct 奖金率
FROM
employees
WHERE
commission_pct <=> null;
#is null pk <=>
#is null:仅仅可以判断null值,可读性较高,建议使用
#<=>:既可以判断null值,又可以判断普通的数值,可读性较低
进阶三:排序查询
引入:
select * from employees;
语法:
select 查询列表
from employees
[where 筛选条件]
order by 排列顺序 【asc|desc】
特点:
1、降序排序desc,升序排序asc,如果不写,默认升序
2、order by 子句中可以支持单个字段、多个字段、表达式、函数、别名
3、order by子句一般是放在查询语句的最后面,limit子句除外
#案例一:查询员工讯息,要求工资从高到低排序
SELECT * FROM employees ORDER BY salary desc;
#案例二:查询部门编号>=90的员工信息,按入职时间的先后进行排序
SELECT * FROM employees WHERE department_id>=90 ORDER BY hiredate asc;
#案例三:按年薪的高低显示员工的信息和年薪 【按表达式排序】
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) desc;
#案例四:按年薪的高低显示员工的信息和年薪 【按别名排序】
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees
ORDER BY 年薪 desc;
#案例五:按姓名的长度显示员工的姓名和工资【按函数排序】
SELECT first_name ,salary FROM employees ORDER BY LENGTH(first_name) asc;
SELECT first_name, LENGTH(first_name) 字节长度 FROM employees ORDER BY 字节长度 ASC;
#案例六:查询员工信息,要求先按工资排序,再按员工编号排序【按多个字段排序】
SELECT * FROM employees ORDER BY salary ASC,employee_id ASC;
test
#1.查询员工的姓名和部门号和年薪,按年薪降序,按姓名升序。
SELECT CONCAT(first_name,' ',last_name) 姓名,department_id 部门号,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 DESC, 姓名 ASC;
#2.选择工资不在8000到17000的员工的姓名和工资,按工资降序。
SELECT CONCAT(first_name,' ',last_name) 姓名,salary 工资 FROM employees WHERE NOT(salary BETWEEN 8000 and 17000) ORDER BY salary DESC;
SELECT CONCAT(first_name,' ',last_name) 姓名,salary 工资 FROM employees WHERE salary not BETWEEN 8000 and 17000) ORDER BY salary DESC;
#3.查询邮箱中包含e的员工信息,并先按邮箱的字节数降序,再按部门号升序。
SELECT * FROM employees WHERE email LIKE '%e%' ORDER BY LENGTH(email) DESC,department_id ASC;
进阶四:常见函数
概念:将一组逻辑语句封装在方法体中,对外暴露方法名 特点:1、隐藏了实现细节 2、提高代码的重用性
调用: select 函数名(实参列表) 【from 表】;#如果函数用到了表中的字段,则需要加from 表
特点:
①叫什么(函数名)
②干什么(函数功能)
分类:
①单行函数
如concat、length、ifnull等
②分组函数
功能:做统计使用,欧成为统计函数、聚合函数、组函数
单行函数:
1、字符函数
2、数字函数
3、日期函数
4、其他函数【补充】
5、流程控制函数【补充】
#一、字符函数
#①length 获取参数值的字节个数
#②concat 拼接字符串
#③upper、lower 大写、小写
#案例:将姓变大写,名变小写,然后拼接
SELECT CONCAT(LOWER(first_name),' ',UPPER(last_name)) FROM employees;
#④substr、substring 截取字符串;注意:索引从1开始
#截取从指定索引处后面的所有字符
SELECT SUBSTR('海绵宝宝和派大星是好朋友',10);
#截取从指定索引出指定字符长度的字符
SELECT SUBSTR('海绵宝宝和派大星是好朋友',6,3);
#案例:姓名中首字符大写,其他字符小写,然后用_拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),'_',LOWER(SUBSTR(first_name,2))) FROM employees;
#⑤instr 返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR('海绵宝宝和派大星是好朋友','派大星');
#⑥trim 去掉前后的字符
SELECT length(TRIM('1' FROM'111111111张111111111cui111111111果11111111'));
#⑦lpad 用指定的字符实现左填充指定长度
SELECT LPAD('殷素素',12,'-');
SELECT LPAD('殷素素',2,'-'); #从左边其保留两个字符
#output:殷素
#⑧rpad 用指定的字符实现右填充指定长度
SELECT LPAD('殷素素',12,'-');
SELECT LPAD('殷素素',2,'-'); #从左边其保留两个字符
#output:殷素
#⑨replace 替换
SELECT REPLACE('张无忌爱上了周芷若','周芷若','赵敏');
#二、数学函数
#round 四舍五入
SELECT ROUND(1.65);
SELECT ROUND(1.567,2);
#ceil 向上取整,返回>=该参数的最小整数
SELECT CEIL(1.02);
#floor 向下取整,返回<=该参数的最小整数
SELECT FLOOR(-9.99);
#truncate 截断,第二个参数是小数点后保留几位
SELECT TRUNCATE(1.59999,2);
#mod 取余
SELECT MOD(10,2);
SELECT 10%3;
#三、日期函数
#1、now 返回当前系统日期+时间
SELECT NOW();
#2、curdate 返回当前系统日期,不包含时间
SELECT CURDATE();
#3、curtime 返回当前时间,不包含日期
SELECT CURTIME();
#4、可以获取指定的部分,年、月、日、小时、分钟、秒
SELECT YEAR(CURDATE());
SELECT YEAR('1991-1-1');
SELECT YEAR(hiredate) FROM employees;
SELECT MONTH(NOW());
SELECT MONTHNAME(NOW());
SELECT DAY(NOW());
SELECT MINUTE(NOW());
SELECT HOUR(NOW());
SELECT SECOND(NOW());
#5、str_to_date 将字符通过指定的格式转换成日期
SELECT STR_TO_DATE('1995-9-2','%Y-%m-%d');
#查询入职日期为1992-4-3的员工信息
SELECT * FROM employees WHERE hiredate = '1992-4-3';
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');
#6、DATE_FORMAT(date,format) 将日期转换成字符
SELECT DATE_FORMAT(NOW(),'%y年%c月%d日');
#查询有奖金的员工名和入职日期(XX月/XX日 XX年)
SELECT first_name as 员工名, date_format(hiredate,'%m月/%d日 %y年') AS 入职日期 FROM employees WHERE commission_pct is not null;
#四、其他函数
SELECT VERSION();
SELECT DATABASE();
SELECT USER();
#五、流程控制函数
#1、if函数:IF(expr1,expr2,expr3);
#if else 的效果
SELECT IF(10>5,'big','small');
SELECT last_name,commission_pct,IF(commission_pct is NOT NULL,'有奖金','没奖金') FROM employees;
#2、case函数的使用一
CASE case_value#要判断的字段或表达式
WHEN when_value#常量1
THEN
statement_list#要显示的值1或语句1
ELSE
statement_list#要显示的值2或语句2
END;
/*案例:查询员工的工资,要求
部门号=30,显示工资的1.1倍
部门号=40,显示工资的1.2倍
部门号=50,显示工资的1.3倍
其他部门,显示原工资
*/
SELECT first_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 新工资
FROM employees;
#3、case函数的使用二:类似多重if
CASE
WHEN when_value#常量1
THEN
statement_list#要显示的值1或语句1
WHEN when_value#常量1
THEN
statement_list#要显示的值2或语句2
...
ELSE
statement_list#要显示的值n或语句n
END;
/* 案例:查询员工的工资情况
如果工资>20000,显示A级别
如果工资>15000,显示B级别
如果工资>10000,显示C级别
否则显示D级别
*/
SELECT salary 工资,
CASE
WHEN salary>2000 THEN
'A'
WHEN salary<=2000 && salary>15000 THEN
'B'
WHEN salary<=15000 && salary>10000 THEN
'C'
ELSE
'D'
END 级别
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 AVG(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
SELECT SUM(salary),round(AVG(salary),2),MAX(salary),MIN(salary) ,COUNT(salary) FROM employees;
#2、参数支持类型
#max min 支持字符型、日期型
#count 支持所有类型,计算非空的值的个数
SELECT SUM(last_name),AVG(last_name) FROM employees;
SELECT SUM(hiredate)
#3、是否忽略null
SELECT SUM(commission_pct),AVG(commission_pct),SUM(commission_pct)/35,SUM(commission_pct)/107 FROM employees;
SELECT MAX(commission_pct),MIN(commission_pct) FROM employees;
SELECT COUNT(commission_pct) FROM employees;
#4、和distinct搭配
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
#5、count函数的详细介绍
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;#统计行数
SELECT COUNT(1) FROM employees;
/*括号中可以是任何值
效率:MYISAM存储引擎下,count(*)的效率高
INNODB存储引擎下,count(*)和count(1)的效率差不多,比count(字段)要高一些
*/
#6、和分组函数一同查询的字段有限制
SELECT AVG(salary),employee_id FROM employees;
#练习
#1.查询公司员工工资的最大值,最小值,平均值,总和
SELECT MAX(salary),MIN(salary) ,AVG(salary),SUM(salary) FROM employees;
#2.查询员工表中的最大入职时间和最小入职时间的相差天数 (DIFFRENCE)
SELECT DATEDIFF(MAX(hiredate),MIN(hiredate)) DIFFRENCE FROM employees;
#3.查询部门编号为90的员工个数
SELECT COUNT(*) FROM employees WHERE department_id=90;
进阶五:分组查询
#引入:查询每个部门的平均工资
SELECT AVG(salary) FROM employees;
/*语法
SELECT 分组函数,列
FROM 表 [WHERE 筛选条件]
GROUP BY 分组的列表
[ORDER BY 子句]
注意:查询列表必须特殊,要求是分组函数和group by后出现的字段
特点:
1、 分组查询中的筛选条件分为两类
数据源 | 位置 | 关键字 | |
---|---|---|---|
分组前筛选 | 原始表 | group by 子句的前面 | where |
分组后筛选 | 分组后的结果集 | group by 子句的后面 | having |
注:①分组函数做条件肯定是放在having子句中;②能用分组前筛选的,就优先考虑使用分组前筛选(考虑性能问题)
2、group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开,没有顺序要求),表达式或函数(用的较少)
3、也可以添加排序(order by,放在整个查询语句的最后)
#简单的分组查询
#案例一:查询每个工种的最高工资
SELECT MAX(salary),job_id FROM employees GROUP BY job_id;
#案例二:查询每个位置上的部门个数
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
#添加筛选条件,分组前的筛选
#案例一:查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE email like '%a%'
GROUP BY department_id;
#案例二:查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;
#添加分组后的筛选条件
#案例一:查询哪个部门的员工个数>2
#①查询哪个部门的员工个数>2
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;
#②根据①的结果进行筛选
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#案例二:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT MAX(salary),job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING max(salary)>12000;
#案例三:查询领导编号>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) a,department_id,job_id
FROM employees
#WHERE department_id IS NOT NULL
GROUP BY department_id,job_id
#HAVING a>10000
ORDER BY AVG(salary) DESC;
练习
#1.查询各job_id的员工工资的最大值,最小值,平均值,息和,并按job_id升序
SELECT MAX(salary),MIN(salary),AVG(salary),SUM(salary),job_id
FROM employees
GROUP BY job_id
ORDER BY job_id ASC;
#2.查询员工最高工资和最低工资的差距(DIFFERENCE)
SELECT MAX(salary),MIN(salary),MAX(salary)-MIN(salary) 工资差距
FROM employees;
#3.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
SELECT MIN(salary),manager_id
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
HAVING MIN(salary)>=6000;
#4.查询所有部门的编号,员工数量和工资平均值,并按平均工资降序
SELECT COUNT(*),AVG(salary),department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) DESC;
#5.选择具有各个job_id的员工人数
SELECT COUNT(*),job_id
FROM employees
GROUP BY job_id;
进阶六:连接查询/连表查询
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表1有m行,表2有n行,结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:
sql92标准【仅支持内连接】;
sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
按功能分类:
内连接:
等值分类
非等值分类
自连接
外连接:
左外连接
右外连接
全外连接
交叉连接
sql92标准
#一、sql92标准
#1、等值连接
/*
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选
*/
#案例一:查询女生名和对应的男神名
SELECT `name`,boyName FROM beauty,boys
WHERE beauty.boyfriend_id=boys.id
ORDER BY boyName DESC;
#案例二:查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.department_id=departments.department_id;
#2、为表起别名
#①提高语句的简洁度
#②区分多个重名的字段
#注意:如果为表起了别名,就不能再用原先的表名了,如:SELECT last_name,employees.job_id,job_title FROM employees e,jobs j
#查询员工名、工种号、工种名
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、可以加筛选
#案例:查询有奖金的员工名、部门名
SELECT first_name,department_name,commission_pct
FROM employees,departments
WHERE commission_pct IS NOT NULL and employees.department_id=departments.department_id;
# 案例二:查询城市名中第二个字符为o的部门名和城市名
SELECT department_name,city
FROM locations,departments
WHERE locations.location_id=departments.location_id AND city LIKE '_o%';
#5、可以加分组
#案例1、查询每个城市的部门个数
SELECT COUNT(*) 部门个数 ,city
FROM departments,locations
WHERE departments.location_id=locations.location_id
GROUP BY city;
#案例二:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
SELECT department_name,d.`manager_id`,MIN(salary)
FROM employees e,departments d
WHERE e.department_id=d.department_id AND commission_pct IS NOT NULL
GROUP BY department_name,d.manager_id;
#6、可以加排序
#案例查询每个工种的工种名和员工个数,并按员工个数降序
SELECT job_title,COUNT(*) 员工个数
FROM jobs,employees
WHERE jobs.job_id=employees.job_id
GROUP BY job_title
ORDER BY 员工个数 DESC;
#7、可以实现三表连接
#案例:查询员工名、部门名和所在的城市
SELECT last_name,d.department_name,city
FROM employees e,departments d,locations l
WHERE e.department_id=d.department_id AND l.location_id=d.location_id;
#2、非等值连接
#案例一:查询员工的工资和工资级别
SELECT salary ,grade_level
FROM employees,job_grades g
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;
测试
#一、显示员工表的最大工资,工资平均值
SELECT MAX(salary),AVG(salary)
FROM employees;
#二、查询员工表的employee_id, job_id, last_name,按departijent_id降序, salary升序
SELECT employee_id,job_id,last_name
FROM employees
ORDER BY department_id DESC ,salary ASC;
#三、查询员工表的job_id中包含 a和e的,并且a在e的前面
SELECT job_id
FROM employees
WHERE job_id LIKE '%a%e%';
#四、已知表student.里面有id(学号), name, gradeld (年级编号)已知表grade,里面有id(年级编号),name(年级名)已知表result,里面有id, score, studentNo (学号)
#要求查询姓名、年级名、成绩
SELECT s.`name`,g.`name`,r.score
FROM student s,grade g,result r
WHERE s.gradeld = g.id AND s.id=r.studentNo
#五、显示当前日期,以及去前后空格,截取子字符串的函数
SELECT NOW()
SELECT TRIM([remstr FROM] str)
SELECT SUBSTR('海绵宝宝和派大星是好朋友',6,3)
76、77
sql99语法
/*
语法:
select 查询列表
from 表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 连接条件
分类:
等值
非等值
自连接
特点:
1、添加排序、分组、筛选
2、inner可以省略
3、筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
4、inner join 和sql92语法中的等值连接效果是一样的,都是查询多表的交集
*/
#(一)、等值连接
#1、查询员工名、部门名
SELECT last_name,department_name
FROM departments d
INNER JOIN employees e
ON e.department_id=d.department_id;
#2.查询名字中包含e的员工名和工种名(筛选)
SELECT last_name,j.job_title
FROM employees e
INNER JOIN jobs j
ON e.job_id=j.job_id
WHERE last_name like '%e%';
#3、查询部门个数>3的城市名名和部门个数, (分组+筛选)
SELECT COUNT(*),city
FROM departments d
INNER JOIN locations l
ON d.location_id=l.location_id
GROUP BY city
HAVING COUNT(*)>3;
#4、查询哪个部门的部门员工个数>3的部门名和员工个数,并按个数降序(排序)
SELECT COUNT(*),d.department_id
FROM departments d
INNER JOIN employees e
ON d.department_id=e.department_id
GROUP BY d.department_id
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
INNER JOIN jobs j ON e.job_id=j.job_id
ORDER BY d.department_name;
#(二)、非等值连接
#查询员工的工资级别
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades jg
ON e.salary BETWEEN jg.lowest_sal AND jg.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,e.employee_id,m.last_name,m.employee_id
FROM employees e
INNER JOIN employees m
ON e.manager_id=m.employee_id;
#查询姓名中包含字符k员工的名字、上级的名字
SELECT e.last_name,e.employee_id,m.last_name,m.employee_id
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没有的
*/
#引入:查询男朋友不在男生表中的女生名
SELECT b.`name`
FROM beauty b
LEFT JOIN boys bo
ON b.boyfriend_id=bo.id
WHERE bo.id is NULL;
#案例一:查询哪个部门没有员工
#左外连接
SELECT department_name,e.*
FROM departments d
LEFT JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id is NULL;
#右外连接
SELECT department_name,e.*
FROM employees e
RIGHT JOIN departments d
ON d.department_id=e.department_id
WHERE e.employee_id is NULL;
#全外:sql99不支持
#三、交叉连接
#笛卡尔乘积
SELECT b.*,bo.*
FROM beauty b
CROSS JOIN boys bo;
sql92和sql99语法pk
功能:sql99支持的较多
可读性:sql99实现连接条件和筛选条件的分离,可读性较高
常见的几种连接
#一、查询编号>3的女神的男朋友信息,如果有则列出详细,如果没有,用null填充
SELECT b.`name`,b.id,bo.*
FROM beauty b
LEFT JOIN boys bo
ON bo.id=b.boyfriend_id
WHERE b.id>3;
#二、查询哪个城市没有部门
SELECT l.city,d.*
FROM locations l
LEFT JOIN departments d
ON d.location_id=l.location_id
WHERE d.department_id is null;
#三、查询部门名为SAL或IT的员工信息
SELECT e.*,department_name
FROM employees e
right JOIN departments d
ON e.department_id=d.department_id
WHERE d.department_name = 'SAL' OR D.department_name = 'IT';
进阶七:子查询
/*
含义:出现在其他语句中的select语句,成为子查询或内查询
外部的查询语句成为主查询或外查询
分类:
按子查询出现的位置:
select后面
仅仅支持标量子查询
from后面
支持表子查询
where或having后面 ❤
标量子查询 ❤单行
列子查询 ❤多行
行子查询(较少)
exists后面(相关子查询)
表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一(多)行多列)
表子查询(结果集一般为多行多列)
*/
一、where或having后面
-- 标量子查询:单行子查询
-- 列子查询:多行子查询
-- 行子查询:多行多列
-- 特点:
-- ①子查询放在小括号内
-- ②子查询一般放在条件的右侧
-- ③标量子查询,一般搭配这单行操作符使用 > < >= <= <>
-- 列子查询一般搭配这多行操作符使用:in any/some all
-- ④ 子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
1、标量子查询
#案例一:查询谁的Abel的工资高?
#①查询Abel的工资
SELECT salary
FROM employees
WHERE last_name = 'Abel'
#②查询员工的信息,满足salary>①的结果
SELECT *
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name = 'Abel'
);
# 案例二:返回job_id与141号员工相同,salary比143号员工多的员工,姓名,job_id和工资
SELECT last_name,e.job_id,salary
FROM employees e
RIGHT JOIN jobs j
ON e.job_id=j.job_id
WHERE e.job_id=(
SELECT job_id
FROM employees
WHERE employee_id =141
)
AND salary>(
SELECT salary
FROM employees f
WHERE f.employee_id=143
);
#案例三:返回公司工资最少的员工的last_name、job_id和salary
SELECT last_name,job_id,salary
FROM employees
WHERE salary = (
SELECT min(salary)
FROM employees
)
#案例四:查询最低工资大于50号部门最低工资的部门id和其最低工资
#50号部门的最低工资
SELECT MIN(salary),department_id
FROM employees
WHERE department_id = 50
#各部门的id和其最低工资
SELECT department_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id = 50
);
2、列子查询(多行子查询)
#案例一:返回location_id是1400或1700的部门中的所有员工姓名
SELECT department_id
FROM departments
WHERE location_id in (1400,1700);
SELECT last_name,department_id
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id in (1400,1700)
);
#案例二:返回其他部门中比job_id为'IT_PROG'部门任一工资低的员工的:工号、姓名、job_id以及salary
SELECT salary
FROM employees
WHERE job_id='IT_PROG'
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ANY (
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
) AND job_id IN(
SELECT job_id
FROM employees
WHERE job_id != 'IT_PROG'
);
#案例三:返回其他部门中比job_id为'IT_PROG'部门所有工资低的员工的:工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ALL (
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
) AND job_id =ANY(
SELECT job_id
FROM employees
WHERE job_id != 'IT_PROG'
);
3、行子查询(结果集一行多列或多行多列)
#2、列子查询(多行子查询)
#案例:查询员工编号最小并且工资最高的员工信息
SELECT MIN(employee_id)
FROM employees
SELECT MAX(salary)
FROM employees
SELECT *
FROM employees
WHERE employee_id = (
SELECT MIN(employee_id)
FROM employees
)
AND salary = (
SELECT MAX(salary)
FROM employees
);
#行子查询:局限性,符号一致
SELECT *
FROM employees
WHERE (employee_id,salary) = (
SELECT MIN(employee_id),MAX(salary)
FROM employees
);
二、select后面
仅仅支持标量子查询
#查询每个部门的员工个数
SELECT d.*,(
SELECT COUNT(*)
FROM employees
WHERE d.department_id=employees.department_id) 员工个数
FROM departments d;
#案例二:查询员工号=102的部门号
SELECT (
SELECT department_name
FROM departments d
WHERE employee_id =102
)
FROM employees
三、from后面
将子查询结果充当一张表,要求必须起别名
#案例:查询每个部门的平均工资的工资等级
SELECT AVG(salary)
FROM employees
GROUP BY department_id;
SELECT ag_dep.* ,g.grade_level
FROM (
SELECT AVG(salary) ag
FROM employees
GROUP BY department_id) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN g.lowest_sal AND g.highest_sal;
四、exists后面(相关子查询)
语法:exists(完整的查询语句)
结果:1/0,判断是否为真
SELECT EXISTS(SELECT employee_id FROM employees WHERE salary = 3000000);
#案例一:
测试
查询和zlotkey相同部门的员工姓名和工资
查询工资比公司平均工资高的员工的员工号,姓名和工资
查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资
查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
5.查询在部门的location_id为1700的部门工作的员工的员工号
6.查询管理者是King的员工姓名和工资
7.查询工资最高的员工的姓名,要求first_name和last_name显示为一列,列名为 姓,名
进阶八:分页查询❤
/*
应用场景:当要显示的数据一页显示不全,需要分页提交sql请求
语法:
SELECT 查询列表
FROM 表
【JOIN type JOIN 表2
ON 连接条件
WHERE 筛选条件
GROUP BY 分组字段
HAVING 分组后的筛选
ORDER BY 排序字段】
LIMIT OFFSET,size;
OFFSET要显示条目的起始索引(起始索引从0开始)
size要显示的条目个数
特点:
1、limit语句放在查询语句的最后
2、公式:
要显示的页数 page,每页的条目数 size
SELECT 查询列表
FROM 表
LIMIT (page-1)*size,size;
*/
#案例一:查询前五条员工信息
SELECT *
FROM employees
LIMIT 0,5;
#案例二:查询第11-25
SELECT *
FROM employees
LIMIT 10,15;
#案例三:有奖金的员工信息,并且工资较高的前10名显示出来
SELECT *
FROM employees
WHERE commission_pct is NOT null
ORDER BY salary DESC
LIMIT 0,10;
P96 测试
已知表stuinfo
id 学号
name 姓名
email 邮箱 john@126. com
gradeId 年级编号
sex 性别 男 女
age 年龄
已知表 grade
id 年级编号
gradeName 年级名称
一、查询所有学员的邮箱的用户名 (注:邮箱中@前面的字符)
二、查询男生和女生的个数
三、查询年龄>18岁的所有学生的姓名和年级名称
四、查询哪个年级的学生最小年龄>20岁
五、试说出查询语句中涉及到的所有的关键字,以及执行先后顺序
P98 案例
#1.查询工资最低的员工信息: last_name, salary
#2.查询平均工资最低的部门信息
#3.查询平均工资最低的部门信息和该部门的平均工资
#4.查询平均工资最高的job信息
#5.查询平均工资高于公司平均工资的部门有哪些?
#6.查询出公司中所有manager的详细信息
#7.各个部门中最高工资中最低的那个部门的最低工资是多少
#8.查询平均工资最高的部门的manager 的详细信息: last_name, department_id, email, salary
进阶九:联合查询
/*
UNION 联合、合并:将多条查询语句的结果合并成一个结果
语法:
查询语句1
UNION
查询语句2
UNION
...
应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时
注意事项:
1、要求多条查询语句的查询列表是一致的
2、要求多条查询语句的查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all可以包含重复项
*/
#引入的案例:查询部门编号>90或邮箱包含a的员工信息
SELECT *
FROM employees
WHERE department_id>90 OR email LIKE '%a%';
SELECT *
FROM employees
WHERE department_id>90
UNION
SELECT *
FROM employees
WHERE email LIKE '%a%';
#案例:查询中国用户中男性的信息以及外国用户中男性的用户信息
DML语言
data manipulation language:数据操作语言。增删改
插入语句:insert
修改语句:update
删除语句:delete
一、插入语句
语法一:
insert into 表名(列名,…) values (值1,…);
SELECT * FROM beauty;
#1、插入的值的类型要与列的类型一致或兼容
INSERT INTO beauty(id,`name`,sex,borndate,phone,photo,boyfriend_id) VALUES(13,'唐艺昕','女','1990-4-23','12323423456',NULL,3);
#2、不可以为null的值必须插入值,可以为null的列如何插入值?
#方式一:用null代替值
INSERT INTO beauty(id,`name`,sex,borndate,phone,photo,boyfriend_id) VALUES(13,'唐艺昕','女','1990-4-23','12323423456',NULL,3);
-- 方式二:列名和值都省略
INSERT INTO beauty(id,`name`,sex,borndate,phone,boyfriend_id) VALUES(14,'娜扎','女','1990-4-23','12234',3);
#3、列的顺序是否可以调换?可以!但必须相互匹配
INSERT INTO beauty(`name`,id,sex,borndate,phone,boyfriend_id) VALUES('娜扎',15,'女','1990-4-23','12234',3);
#4、列数和值的个数必须一致
#5、可以省略列名,默认所有列,且列的顺序和表中的顺序一致
INSERT INTO beauty
VALUES(18,'张飞','女',NULL,'911',NULL,NULL)
/*
语法二:
INSERT INTO 表名
SET 列名=值,列名=值,...
*/
INSERT INTO beauty
SET id=17,`name`='刘涛',sex='女',phone='12345';
#两种方式大PK
1、语法一支持插入多行,语句二不支持
INSERT INTO beauty
VALUES(28,'张飞1','女',NULL,'911',NULL,NULL),
(38,'张飞2','女',NULL,'911',NULL,NULL),
(48,'张飞3','女',NULL,'911',NULL,NULL)
#语句一支持子查询,语句二不支持
INSERT INTO beauty(id,NAME,phone)
SELECT 26,'宋茜','123532342';
INSERT INTO beauty(id,`name`,phone)
SELECT id,boyname,'123123'
FROM boys WHERE id<3;
二、修改语句
/*
1、修改表的记录
语法:
UPDATE 表名
SET 列=新值,列=新值,...
WHERE 筛选条件;
2、修改多表的记录【补充】
语法:
sql92语法:
update 表1 别名,表2 别名
set 列=值,...
where 连接条件
and 筛选条件;
sql99语法:
update 表1 别名
inner|left|right join 表2 别名
on 连接条件
set 列=值,...
where 筛选条件;
*/
SELECT * FROM beauty;
#1、修改单表的记录
#案例一:修改beauty表中姓唐的女神的电话为13899888899
UPDATE beauty
SET phone='13899888899'
WHERE `name` LIKE '唐%';
#案例二:修改boys表中id为2的名称为张飞,魅力值10
SELECT * FROM boys;
UPDATE boys
SET boyName='张飞',userCP=10
WHERE id=2;
#2、修改多表的记录
#案例1:修改张无忌的女朋友的手机号为114
#inner JOIN:将两张表格拼接在一起
UPDATE beauty b
INNER JOIN boys bo
ON b.boyfriend_id=bo.id
SET phone=114
WHERE bo.id=1;
#案例2:修改没有男朋友的女神的男朋友编号都为2号
#左连/右连,找出某一张表符合条件的数据,左连:主表在前,右连,主表在后
UPDATE beauty b
LEFT JOIN boys bo
ON b.boyfriend_id=bo.id
SET b.boyfriend_id=2
WHERE bo.id is null;
SELECT * FROM beauty
三、删除语句
/*
方式一:delete
语法:
1、单表的删除❤
delete FROM 表名 where 筛选条件
2、多表的删除【补充】
sql92语法:
DELETE 表1的别名,表2的表名
FROM 表1 别名,表2 别名
WHERE 连接条件
and 筛选条件
sql99语法:
DELETE 表1的别名,表2的表名
FROM 表1 别名
INNER|LEFT|RIGHT JOIN 表2 别名
ON 连接条件
WHERE 筛选条件
方式二:truncate:删除整个表的数据,不能加where条件
语法:TRUNCATE TABLE 表名;
*/
#方式一:delete
#1、单表的删除
#案例1:删除手机号以9结尾的女神信息
DELETE FROM beauty WHERE phone LIKE '%9';
SELECT * FROM beauty
#2、多表的删除
#案例:删除张无忌的女朋友的信息
DELETE b
FROM boys bo
INNER JOIN beauty b
ON bo.id=b.boyfriend_id
WHERE bo.boyName='张无忌';
#案例:删除黄晓明以及他女朋友的信息
DELETE b,bo
FROM boys bo
INNER JOIN beauty b
ON bo.id=b.boyfriend_id
WHERE bo.boyName='黄晓明';
/*
#方式二:truncate语句
TRUNCATE TABLE boys;
#DELETE pk TRUNCATE
1、delete可以加where条件,truncate不能加
2、truncate删除,效率高
3、假如要删除表中有自增长列,如果用delete删除后在插入数据,自增长列的值从断点开始,而truncate删除后,再插入数据,自增长列的值从1开始。
4、truncate删除没有返回值,delete删除有返回值
5、truncate删除不能回滚,delete删除可以回滚
*/
DDL语言
data define language:数据定义语言,如何创建库,如何创建表;如何删除库,如何删除表等
库和表的管理
常见数据类型介绍
常见约束
drop database if exists books;
二、表的管理
1、表的创建
/*
语法:
create table 表名(
列名 列的类型【(长度)约束】,
列名 列的类型【(长度)约束】,
列名 列的类型【(长度)约束】,
…
列名 列的类型【(长度)约束】
)
#案例:创建表book
CREATE TABLE book(
id INT,#编号
bName VARCHAR(20),
price DOUBLE,#价格
authorId INT,#作者id
publishDate DATETIME#出版日期
);
DESC book;
#案例:创建表author
CREATE TABLE author(
id INT,
au_name VARCHAR(20),
nation VARCHAR(10)
);
DESC author;
#2、表的修改
#①修改列名
ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;
#②修改列的类型或约束
ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;#时间戳
#③添加新列
ALTER TABLE author ADD COLUMN annual DOUBLE;
#④删除列
ALTER TABLE author DROP COLUMN annual;
#⑤修改表名
ALTER TABLE author RENAME TO book_author;
#3、表的删除
DROP TABLE