My SQL基础语法速查

1 数据库的好处

  1. 可以持久化数据到本地
  2. 结构化查询

2 数据库的常见概念

  1. DS:数据库,存储数据的容器
  2. DBNS:数据库管理系统,又称为数据库软件或数据库产品,用于创建或管理DB
  3. SQL:结构化查询语言

3 数据库存储数据的特点

  1. 数据存到列表中,然后再放回到库中
  2. 一个库中可以有多张表,每张表具有唯一的表名用来标识自己
  3. 表中有一个或多个列,列又称为“字段”,相当于属性
  4. 表中的每一行数据库,相当于java中‘对象’

4 语法规范

  1. 不区分大小写
  2. 每条命令用分号结尾
  3. 每条命令根据需要可以进行缩进和换行
  4. 单行注释: #或–
  5. 多行注释:/* 注释文字 */

5 常见命令

  1. show databases; 显示数据库
  2. use 库名; 进入某个指定库
  3. show tables from xx(库名); 展示某个库当中的表
  4. select database(); 查看当前所在库
  5. select * from (表名); 看表当中的数据
  6. create table name(id int, name varchar(20)); 创建一个表
  7. insert into name (属性名) values (值)
  8. desc 表明; 查看某表的结构

6 DQL语言

# 进阶1:基础查询
# select 查询表 from 表名;
# 查询列表可以是:表中的字段、常量值、表达式、函数
# 查询的结果是虚拟的表格
# 打开库


# 1.查询单个字段
SELECT last_name From employees;

# 2.查询多个字段
SELECT last_name,salary,email FROM employees;

# 3.查询所有字段,表中的顺序一模一样
SELECT * FROM employees;

# 4.查询常量值
SELECT 100;
SELECT 'john';

# 5.查询函数
SELECT VERSION();

# 6.查询表达式
SELECT 100%98

# 7.1 起别名
SELECT 100%98 AS 结果;
SELECT last_name as, first_name asFROM employees; 

# 7.2 起别名
SELECT last_name 姓,first_name 名 FROM employees;

# 7.3 别命有特殊符号
SELECT last_name AS 'out put' FROM employees;

# 8. 去重
SELECT DISTINCT department_id FROM employees;

# 9. +号作用:仅仅只能充当运算符
# 查询员工名和姓,连接成一个字段,并显示为 姓名
SELECT CONCAT(last_name,' ',first_name) AS 姓名 FROM employees;

# 10.显示表结构
DESC departments;

# 11.自定义null的输出
SELECT IFNULL(commission_pct,0) AS 奖金率,
				commission_pct
From
				employees;
# 进阶2:条件查询
/*
语法:
			SELECT
						查询列表
			FROM 
						表名
			WHERE
						筛选条件;
分类:
			一、按条件表达式筛选
			条件运算符:> < = != <> <= >=
			
			二、逻辑运算符
			&& || !
			and or not
			
			三、模糊查询
							like
							between
							in
							is null
*/

# 一、按条件表达式筛选

#案例1:查询员工工资大于12000的人

SELECT concat(last_name,'-',first_name) AS 姓名 from employees where salary >= 12000;

SELECT * from employees where salary >= 12000;

#案例2:查询部门编号不等于90号的员工名和部门编号
SELECT 
			CONCAT(last_name,' ',first_name,' id:',department_id) as INFO 

FROM
			employees
WHERE
			department_id <> 90;
			
# 二、按逻辑表达式
# 案例1:工资在10000到20000之间的员工名、工资及奖金

SELECT 
				CONCAT(last_name,' ',first_name) AS 姓名,
				salary AS 工资,
				commission_pct AS 奖金,
FROM
				employees
WHERE
				salary>10000 and salary<20000;
				
# 案例2:查询部门编号不是在90-110,或者工资高于15000的员工信息
SELECT *
FROM	employees
WHERE ((0<department_id<90) OR (110<department_id)) OR salary>15000; 
SELECT job_id FROM employees WHERE salary>10000;

# 三、模糊查询
/*
like
like搭配通配符使用;
通配符:
1.% 任意多个字符,包含0个或多个字符
2._ 任意单个字符
between
in
in null | is not null
*/
# 案例1:查询员工名中包含字符a的员工信息
SELECT * From employees WHERE last_name LIKE '%a%'; # %当作通配符

#案例2:查询员工名中第三个字符为a,第五个字符为a的员工名
SELECT last_name from employees where last_name LIKE '__a_l%';

#案例3:查询员工名中第二个字符为下划线的员工名
SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$'; #ESCAPE 表转义

#2.between and

#案例1:查询员工编号在100-120之间的员工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120; #闭区间

#3.in
#案例1:查询员工的工种编号是:AD_VP,IT_PROG,AD_PRES

SELECT
			last_name,job_id
FROM
			employees
WHERE
			job_id IN ('AD_Vp','IT_PROT','AD_PRES');

# 4.isnull
#案例1:没有奖金的员工名和奖金率

SELECT
			last_name,commission_pct
FROM
			employees
WHERE
			commission_pct IS NULL;

#安全等于 <=>:判断是否等于
SELECT
			last_name,commission_pct
FROM
			employees
WHERE
			commission_pct <=> NULL;

/* is null PK <=>
is null 只能判断 null值,可读性高
<=> 能判断 null 和 is not null ,可读性低
*/

SELECT
			last_name,
			department_id,
			salary*12*IFNULL(1+commission_pct,0) AS 年薪
FROM
			employees
WHERE
			job_id = 176;
			
# 练习:
# 一、查询没有奖金,且工资小于18000的salary,last_name

SELECT
			salary,
			last_name
FROM
			employees
WHERE
			(commission_pct is null) and (salary<18000);
			
#二、查询employees表的结构,job_id不为“IT”或者 工资为12000的员工信息

DESC employees;

SELECT
			*
FROM
			employees
WHERE 
			(job_id not LIKE 'IT%') OR (salary = 12000);
			
# 三、查看departments表的结构
DESC departments;

#四、查询部门departments表中涉及到了哪些位置编号
SELECT
			department_id
FROM
			departments;
			
#五、访问select * from employees和 select * from employees WHERE commission_pct like '%%' and last_name like '%%';看看结果是否一样说明为什么

SELECT * FROM employees;
SELECT * FROM employees WHERE commission_pct LIKE '%%' AND last_name LIKE '%%';
#进阶3:排序查询

/*
引入:

			select * from employees;
语法:
			select 查询表
			from 表
			【WHERE 筛选条件】
			order by 排序列表 【asc | desc】
*/

#案例1:查询员工信息,工资从高到底排序

SELECT * FROM employees ORDER BY salary DESC;

#案例2:查询部门编号>=90的员工信息,按入职时间的先后进行排序

SELECT * FROM employees WHERE department_id >=90 order by hiredate ASC;

#案例3:按年薪的高低显示员工的信息和年薪【按表达式查询】
SELECT *,salary*12*(IFNULL(commission_pct,0)+1) AS 年薪 FROM employees ORDER BY salary*12*(IFNULL(commission_pct,0)+1) DESC;

#案例4:按年薪的高低显示员工的信息和年薪【按别名查询】
SELECT *,salary*12*(IFNULL(commission_pct,0)+1) AS 年薪 FROM employees ORDER BY 年薪 DESC;

#案例5:按姓名的长度显示员工的姓名和工资
SELECT LENGTH(last_name) 字节长度,last_name,salary from employees ORDER BY 字节长度;

#案例6:查询员工信息,要求先按工资排序,再按员工编号排序【按多个字段排序】

SELECT *
FROM employees
ORDER BY salary ASC,job_id DESC;

#查询员工的姓名、部门号和年薪,按年薪降序,按姓名升序

SELECT last_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 DESC, last_name ASC;

#查询工资不在8000到17000的员工的姓名和工资,按工资降序

SELECT last_name,salary FROM employees WHERE salary<8000 OR salary>17000 ORDER BY salary DESC;

#查询邮箱中包含e的员工信息,并先按邮箱的字节数据降序,再按部门号升序

SELECT * FROM employees WHERE email LIKE '%e%' ORDER BY LENGTH(email) DESC,department_id ASC;

#进阶4:常见函数

/*
功能:就是python中的封装函数
调用:select 函数名(实参列表) FROM 表;

分类:
		1、单行函数
		如 concat、length、ifnull等
		2、分组函数
*/

# 一、字符函数
#1.LENGTH 
SELECT length('wada');

#2.concat 拼接

#3.upper,lower
select concat(upper(last_name),lower(first_name)) 姓名 FROM employees;

#4.substr

SELECT SUBSTR('李莫愁爱上了陆展元',6) out_put; #索引从1开始
SELECT SUBSTR('李莫愁爱上了陆展元',1,3) out_put;  #切片截取

#案例:姓名中首字母大写,其他字母小写,然后用_拼接,显示出来;
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) FROM employees;

#5.instr 返回字串第一次出现的索引
SELECT INSTR('杨不美爱上了我的我','我的我') as out_put; # 返回子字符串的起始索引

#6.trim 取出前后的指定字符
SELECT TRIM('d' FROM'd     d d d    d') out_put;

#7.lpad,rpad 左填充,右填充
SELECT LPAD('殷素素',10,'*') AS out_put; #

#8.replace 替换
SELECT REPLACE('aassd','a','q') AS out_put;
/* Built-in Functioin: 
1.LENGTH()
2.INSTR()
3.SUBSTR()
4.TRIM()
5.LPAD/RPAD()
6.REPLACE()
*/

# 二、数学函数
# round 四舍五入

SELECT ROUND(1.653,2);


#ceil 向上取整,返回大于等于x的最小整数
SELECT CEIL(0.1);

#floor 向下取整
SELECT FLOOR(0.1);

#truncate 截断

SELECT TRUNCATE(1.65,1);

#MOD取余

SELECT MOD(-10,-3);

#三、日期函数

#NOW() 返回当前系统日期

SELECT NOW();

#CURDATE() 返回当前日期,不包含时间

#CURTIME() 返回当前时间,不包含日期

#可获得指定的部分,年、月、日、小时、分钟、秒
SELECT YEAR(NOW());

SELECT YEAR(hiredate) FROM employees;

SELECT MONTH(hiredate) FROM employees;

SELECT MONTHNAME(hiredate) FROM employees;

#STR_TO_DATE(str,format) 字符转日期

SELECT STR_TO_DATE('09-1-2020','%m-%d-%Y');

#查询入职日期为4月3号的日期

SELECT * FROM employees WHERE hiredate = '1992-4-3';

SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3-1992','%c-%d-%Y');

#DATE_FORMAT(date,format)

SELECT DATE_FORMAT(NOW(),'%Y-%c-%d');

#查询有奖金的员工名和入职日期(xx月/xx日/xx年)

SELECT last_name 姓名,DATE_FORMAT(hiredate,'%m月/%d日/%y年') 入职日期 FROM employees WHERE commission_pct is NOT NULL;

#四、其他函数

SELECT VERSION();

SELECT DATABASE();

SELECT user();

#五、流程控制函数
#1.if函数

SELECT IF(10>5,'大','小');

SELECT last_name,commission_pct,IF(commission_pct is not NULL,'有奖金','无奖金') 
FROM employees;

#2.CASE函数的使用一: 

/*case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
*/

/*案例:查询员工的工资
要求:
部门=30,显示工资为1.1倍
部门=40,显示工资为1.2倍
部门=50,显示工资为1.3倍
部门=60,显示工资为1.4倍
其他部门,显示为原工资
*/

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
/*
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>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 avg(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

#2、参数支持哪些类型
SELECT MAX(last_name),MIN(last_name) FROM employees;

#3.忽略null
SELECT SUM(commission_pct),AVG(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(*) FROM employees; #统计行数

SELECT COUNT(1) FROM employees; #相当于加了一列常量值然后统计行数

#6.和分组函数一同查询的字段有限制;
SELECT AVG(salary),employee_id FROM employees;

#练习:

#1.查询公司员工工资的最大值、最小值、平均值、总和

SELECT MAX(salary),MIN(salary),AVG(salary),AVG(salary),SUM(salary) FROM employees;

#2.查询员工表中的最大入职时间和最小入职时间的相关天数
SELECT DATEDIFF(MAX(hiredate),MIN(hiredate)) 'DIFFRENCE' FROM employees;

#3.查询部门编号为90的员工个数

SELECT COUNT(*) FROM employees WHERE department_id=90;
#进阶5:分组查询
/*

语法:
			select 分组函数,列(要求出现在group by的后面)
			from 表
			【where 筛选条件】
			group by 分组列表
			【order by 子句】
注意:
			查询列表必须特殊,要求是分组函数和group by后出现的字段

特点:
		1、分组查询中的筛选条件分为两类
					数据源			位置			关键字
		分组前筛选   原始表			group by子句的前面 	WHERE
		分组后筛选	原始表			group by子句的后面 HAVING
		注:分组函数做条件筛选肯定是放在having子句中
			能用分组前筛选的,就优先考虑使用分组前筛选
		2、group by子句支持单个字段分组
		3、也可以添加排序
*/
#引入:查询每个部门的平均工资
SELECT AVG(salary) FROM employees;

#案例1:查询每个工种的最高工资

SELECT MAX(salary),job_id FROM employees
GROUP BY job_id;

#案例2:查询每个位置上的部门个数
SELECT COUNT(*),department_id FROM departments GROUP BY location_id;


#添加筛选条件
#案例1:邮箱中包含a字符的,每个部门的平均工资

SELECT AVG(salary) FROM employees WHERE email LIKE '%a%' GROUP BY department_id;

#案例2:查询有奖金的每个领导手下员工的最高工资

SELECT manager_id,MAX(salary) 最高工资 FROM employees WHERE commission_pct is not null GROUP BY manager_id;

#添加复杂的筛选条件

#案例1:查询哪个部门的员工个数>2,添加分组后的筛选

SELECT COUNT(*) 员工个数,department_id FROM employees GROUP BY department_id
HAVING 员工个数>2
;

#案例2:查询每个工种有奖金的员工的最高工资,最高工资>12000的工资编号和其最高工资

SELECT MAX(salary) 最高工资, job_id 工种编号 FROM employees WHERE commission_pct is not null GROUP BY job_id
HAVING 最高工资>12000;

#案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资

SELECT manager_id 领导编号,MIN(salary),job_id FROM employees WHERE manager_id>102
GROUP BY 领导编号
HAVING MIN(salary) >5000;
#进阶6:连接查询
/*
含义:又称多表查询,当查询字段来自于多个表时,就会用到连接查询

笛卡尔乘积现象:表1 有m行,表2有n行,结果m*n行

发生原因:没有有效的连接条件
如何避免:添加有效的连接条件

分类:
			按年代分类
			sql92标准
			sql99标准【推荐】
			
			按功能分类:
							内连接:
											等值连接
											非等值连接
											自连接
							外连接:
											左外连接
											右外连接
											全外连接
							交叉连接
*/


#一、sql92标准
/*

1.多表等值连接的结果为多表的交集部分
2.n表等值连接,至少需要n-1个条件
3.一般需要为表起别名
4.多表的顺序没有要求
5.可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

*/
#1.等值连接

#案例1:查询女神名和对应的男神名
SELECT `name`,boyName FROM beauty,boys
WHERE beauty.boyfriend_id = boys.id;

#案例2:查询员工名和对应的部门名
SELECT last_name 员工名, department_name 部门名 FROM employees,departments 
WHERE employees.department_id = departments.department_id;

#2.查询员工名、工种号、工种名
/*
为表起别名

1.提高简洁度
2.区分多个重名的字段

注意:如果为表起了别名,则查询字段就不能使用原来的表名去限定
*/
SELECT last_name 员工名,e.job_id 工种号, job_title 工种名
FROM employees e,jobs
WHERE e.job_id = jobs.job_id;


#3.筛选
#案例1:查询有奖金的员工名、部门名

SELECT last_name,department_name
FROM employees E, departments D
WHERE E.department_id = D.department_id AND 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%';


#4.分组

#案例1:查询每个城市的部门个数

SELECT city 城市, count(*) 部门个数
FROM locations L,departments D
WHERE L.location_id=D.location_id
GROUP BY 城市;

#案例2:查询有奖金的每个部门的部门名和部门的领导编号和部门的最低工资

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 部门名,D.manager_id;

#5.排序

#案例:查询每个工种的工种名和员工的个数,并且按员工个数降序

SELECT job_title 工种名, COUNT(*) 员工个数
FROM employees e,jobs j
WHERE e.job_id = j.job_id
GROUP BY 工种名
ORDER BY 员工个数 DESC;

#6.三表连接
#案例:查询员工名、部门名和所在城市
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;

#2、非等值连接
# 插入表

CREATE TABLE job_grades
(grade_level VARCHAR(3),
lowest_sal INT,
highest_sal INT);

INSERT into job_grades
VALUES ('A',1000,2999);

INSERT into job_grades
VALUES ('B',3000,5999);

INSERT into job_grades
VALUES ('C',6000,9999);

INSERT into job_grades
VALUES ('D',10000,14999);

INSERT into job_grades
VALUES ('E',15000,24999);

INSERT into job_grades
VALUES ('A',25000,40000);

#案例1:查询员工的工资和工资级别
SELECT salary,grade_level 
FROM employees E,job_grades J
WHERE salary BETWEEN J.lowest_sal AND J.highest_sal;


#3.自连接

#案例:查询员工名和其上级的名称
SELECT e.last_name 员工名, e.employee_id 员工编号, m.last_name,m.manager_id 上级编号
FROM employees e,employees m 
WHERE e.manager_id = m.employee_id;

SQL99
#二、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 l连接条件


分类:
等值
非等值
自连接

特点:
1.添加排序、分组、筛选
2.inner可以省略
3.筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
4.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 j.job_id = e.job_id
WHERE e.last_name LIKE '%e%';

#案例3:查询部门个数>=3的城市名和部门个数

SELECT city 城市名, count(*) 部门个数
FROM locations l
INNER JOIN departments d
on l.location_id =d.location_id
group by city
having 部门个数>=3;

#案例4:查询部门员工个数>3的部门名和员工个数,并按个数降序(排序)

SELECT department_name 部门名,COUNT(*) 员工个数
FROM departments d
INNER JOIN employees e
on d.department_id =e.department_id
GROUP BY department_name
HAVING 员工个数>3
ORDER BY 员工个数 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 部门名 DESC;

#二)、非等值连接
#查询员工的工资级别
SELECT salary 工资,grade_level 工资级别
FROM employees e 
inner join job_grades g
on e.salary BETWEEN g.lowest_sal and g.highest_sal;

#查询每个工资级别的个数>20的个数,并且按工资级别降序
SELECT COUTN(*) 个数,grade_level 工资级别
FROM employees e
INNER JOIN job_grades g
ON e.salary BETWEEN g.lowest_sal and g.highest_sal
GROUP BY 工资级别
HAVING COUNT(*)>20
ORDER BY 工资级别 DESC;

#三)、自连接
#查询员工的名字、上级的名字
SELECT e.last_name,m.last_name
FROM employees e
INNER JOIN employees m
ON e.manager_id = m.employee_id;

#二、外连接
/*
应用场景:用于查询一个表中有,另一个表没有的记录

特点:
1、外连接的查询结果为主表中的所有记录
			如果从表中有和它匹配的,则显示匹配的值
			如果从表中没有和它匹配的,则显示null
			外连接查询结果=内连接结果+主表中有而从表没有的记录
2、左外连接:left join左边的是主表
	 右外连接:right join右边的是主表
	 
3、左外和右外交换两个表的顺序,可以实现同样的效果
*/
#引入:查询没有男朋友的女神名

#左外连接
SELECT b.name,bo.*
FROM beauty b
left outer join boys bo 
on b.boyfriend_id = bo.id;



#案例1:查询哪个部门没有员工
SELECT d.*,e.employee_id
FROM departments d
left outer join employees e
on e.department_id = d.department_id
HAVING e.employee_id is null;

#交叉连接 CROSS JOIN 其实就是笛卡尔乘积

#练习1:查询编号>3的女神的男朋友信息
SELECT bo.*, b.id
FROM beauty b
LEFT JOIN boys bo
ON bo.id = b.boyfriend_id
WHERE b.id >3;

#练习2:查询哪个城市没有部门
SELECT city 城市
FROM locations l
left join departments d
on d.location_id = l.location_id
WHERE d.location_id is NULL;

#练习3:查询部门名为SAL或IT的员工信息
SELECT d.department_name,e.*
FROM employees e 
RIGHT JOIN departments d
ON e.department_id = d.department_id
WHERE d.department_name = 'SAL' 
or d.department_name = 'IT';

子查询
#进阶7:子查询

/*
含义:
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询

分类:
按子查询出现的位置:
						select后面:
										仅仅支持标量子查询
						from后面:
										支持表子查询
						where或having后面:
										标量子查询(单行)
										列子查询(多行)
										行子查询
						exists后面(相关子查询):
										表子查询
按结果集的行列数不同:
						标量子查询(结果集只有一行一列)
						列子查询(结果集只有一列多行)
						行子查询(结果集有一行多列)
						表子查询(结果集一般为多行多列)

*/

#一、WHERE或HAVING后面
/*
1.标量子查询
2.列子查询
3.行子查询

特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配着单行操作符使用
4.子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
> < >= <= = <>

列子查询:一般搭配着多行操作符使用
in、any/some、all

*/
#1.标量子查询
#案例1:谁的工资比Abel高?
SELECT * FROM employees
WHERE salary>
(
SELECT salary FROM employees
WHERE last_name ='Abel'

);



#案例2:查询job_id与141号员工相同,salary比143号员工多的员工 姓名、job_id和工资

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
 SELECT last_name,job_id,salary
 FROM employees
 WHERE salary = 
 (
 SELECT MIN(salary) FROM employees
);

#案例4:查询最低工资>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
);
#多行子查询
/*
操作符:
			1.IN/NOT IN 等于列表中的任意一个
			2.ANY|SOME 和子查询返回的某一个值比较
			3.ALL 和子查询返回的所有值比较

*/

#案例1:返回location_id是1400或1700的部门中的所有员工姓名
SELECT department_name,location_id
from departments GROUP BY location_id
WHERE location_id =1400


SELECT last_name FROM employees
WHERE department_id IN 
(
		SELECT DISTINCT department_id
		from departments
		WHERE location_id IN (1400,1500)
);



#案例2:返回其他部门中比job_id为"IT_PROG"部门任一工资低的员工的工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ANY(
			SELECT salary 
			FROM employees
			WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG';

#案例3:返回其它部门中比job_id为'IT_PROG'部门所有工资都低的员工的员工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < 
(
SELECT MIN(salary) FROM employees
WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG';

#3.行子查询
#案例:查询员工编号最小并且工资最高的员工信息
SELECT * FROM employees
WHERE (employee_id,salary)=
(
SELECT MIN(employee_id),MAX(salary) FROM employees
);

SELECT * FROM employees
WHERE employee_id = 
(
SELECT MIN(employee_id) FROM employees
) AND salary =
(
SELECT MAX(salary) FROM employees
);



#二、select 后面
#注:只支持标量子查询
#案例1:查询每个部门的员工个数

SELECT d.*,
(
SELECT COUNT(*) FROM employees e
WHERE e.department_id = d.department_id
) 个数
FROM departments d;

#案例2:查询员工号=102的部门名

SELECT
(
	SELECT department_name FROM departments d
	INNER JOIN employees e
	ON e.department_id =d.department_id
	WHERE e.employee_id = 102
);

#三、from后面
/*
将子查询结果充当一张表,要求必须起别名
*/

#案例:查询每个部门的平均工资的工资等级

SELECT aga.*,department_id,grade_level
FROM 
(
	SELECT AVG(salary) ag,department_id FROM employees
	GROUP BY department_id

) aga 
INNER JOIN job_grades g
ON aga.ag BETWEEN g.lowest_sal and g.highest_sal;

#四、exists后面(相关子查询)
/*
语法:
			exists(完整的查询语句)
结果:0,1 
有值为1
*/

#案例1:查询有员工的部门名

SELECT department_name
FROM departments d
WHERE EXISTS(
			SELECT * FROM employees e
			WHERE e.department_id =d.department_id
);

#案例2:查询没有女朋友的男神信息



SELECT bo.* FROM boys bo
WHERE NOT EXISTS(
	SELECT * FROM beauty b
	WHERE bo.id = b.boyfriend_id
);


#练习
#1.查询和Zlotkey相同部门的员工姓名和工资

SELECT last_name,salary,department_name FROM employees,departments
WHERE department_name = (
SELECT department_name FROM departments d,employees e
WHERE last_name = 'Zlotkey' AND d.department_id =e.department_id
);

#2.查询工资比公司平均工资高的员工的员工号,姓名和工资

SELECT employee_id,last_name,salary FROM employees e
WHERE salary > (

SELECT avg(salary) FROM employees
);


#3.查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资
SELECT employee_id,last_name,salary FROM 
(
SELECT AVG(salary) aa,department_id FROM employees
GROUP BY department_id
)  A 
INNER JOIN employees e
ON e.department_id = A.department_id
WHERE salary>A.aa;


#4.查询和姓名中包含字母u的员工在相同部门工作的员工的工号和姓名

SELECT employee_id,last_name FROM employees
WHERE department_id IN(
SELECT DISTINCT department_id FROM employees
WHERE last_name LIKE '%u%'
);

SELECT employee_id,last_name FROM(
					SELECT DISTINCT department_id FROM employees
					WHERE last_name LIKE '%u%'

) d INNER JOIN employees e
on d.department_id = e.department_id
WHERE e.department_id;

#5.查询管理者为King的员工姓名和工资
SELECT last_name,salary FROM employees e
WHERE e.manager_id IN (
SELECT employee_id FROM employees m
WHERE m.last_name = 'K_ing'
);
#进阶8:分页查询
/*

应用场景:当要显示的数据一页显示不全,需要分页提交sql请求

语法:
				SELECT 查询列表
				from 表明
				【join type join 表】
				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
				
				size=10
				page
				1      0
				2      10
				3      20
*/

#案例1 :查询前5条员工信息

SELECT * FROM employees LIMIT 0,5;

#案例2:查询第11条到第25条员工信息
SELECT * FROM employees LIMIT 10,15;

#案例3:有奖金,并且工资排在前10名的员工信息

SELECT * FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 0,10;

#查询所有是领导的员工的姓名

SELECT last_name FROM employees
WHERE employee_id IN
(
SELECT manager_id FROM employees
);


#练习
#1.查询工资最低的员工信息:last_name,salary
SELECT last_name,salary FROM employees
WHERE salary = (SELECT MIN(salary) FROM employees
);
#2.查询平均工资最低的部门信息
#方式1:
SELECT * FROM departments
WHERE department_id = (
SELECT department_id FROM employees e
GROUP BY e.department_id 
order by AVG(salary) ASC
LIMIT 1);

#方式2:
SELECT AVG(salary),department_id FROM employees 
GROUP BY department_id;

SELECT MIN(ag)
FROM 
(
SELECT AVG(salary) ag,department_id FROM employees 
GROUP BY department_id
) agg;

SELECT d.* FROM departments d
WHERE d.department_id =
				(SELECT department_id
				FROM employees
				GROUP BY department_id
				HAVING AVG(salary) = 
(
										SELECT MIN(ag)
										FROM 
										(
												SELECT AVG(salary) ag,department_id FROM employees 
												GROUP BY department_id
										) agg
			)
);
#3.查询平均工资最低的部门信息和该部门的平均工资
SELECT d.*,ag 
FROM departments d
INNER JOIN
(
			SELECT AVG(salary) ag,department_id 
			FROM employees
			GROUP BY department_id 
			ORDER BY AVG(salary) ASC
			LIMIT 1
) agg
on agg.department_id = d.department_id;

#4.查询平均工资最高的 job 信息

SELECT j.* FROM jobs j
WHERE j.job_id =
(
		SELECT job_id FROM employees
		GROUP BY job_id
		order by AVG(salary) DESC
		LIMIT 1
);

#5.查询平均工资高于公司平均工资的部门有哪些
SELECT department_id,avg(salary) FROM employees
GROUP BY department_id
HAVING AVG(salary)>
(

SELECT AVG(salary)
FROM employees
);



#6.查询公司中所有manager的详细信息
	SELECT e.* FROM employees e
	WHERE e.employee_id IN
	(
		SELECT employee_id FROM employees
		WHERE employee_id IN 
			(
			SELECT manager_id FROM employees
			)
	);
#7.各部门中 最高工资中最低的那个部门的最低工资是多少
SELECT MIN(salary) FROM employees
WHERE department_id = (
SELECT department_id FROM employees
GROUP BY department_id
ORDER BY MAX(salary) desc 
LIMIT 1);

#8.查询平均工资最高的部门的manager的详细信息:
SELECT
		last_name,d.department_id,email,salary
FROM employees e
INNER JOIN departments d
ON d.manager_id = e.employee_id
WHERE d.department_id =( 
				SELECT department_id FROM employees
				GROUP BY department_id
				ORDER BY AVG(salary) DESC
				LIMIT 1
);
#进阶9:联合查询
/*
union:将多条查询语句的结果合并成一个结果

语法:
查询语句1
UNION
查询语句2
WHERE

应用场景:
当要查询的结果来自多个表,且多个表之间没有连接关系,且查询的结果一样。

特点:
1.要求多条查询语句的查询列数是一致的
2.要求多条查询语句顺序是一致的
3.会自动去重 用ALL可以取消去重
*/
#引入的案例:查询部门编号>90或邮箱包含a的员工信息

SELECT * 
FROM employees
WHERE department_id >90 OR email like '%a%';

SELECT * FROM employees WHERE email LIKE '%a%'
UNION
SELECT * FROM employees WHERE department_id >90;

7 DML

#DML语句
/*
数据操作语言
插入:insert
修改:update
删除:delete

*/

#一、插入语句
/*
方式一:
语法:
表明
列名
值

insert into 表名(列名...) values(值1,..);

方式二:
insert into 表名
set 列名=值,列名=值,...
*/

#1.插入的值类型要与列的类型一致或兼容

INSERT INTO beauty(id,`name`,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'古力娜扎','女','1994-1-7','122222222',NULL,2);


SELECT * FROM beauty;


#2.可以为NULL的列是如何插入值的

INSERT INTO beauty(id,`name`,sex,borndate,phone,boyfriend_id)
VALUES(14,'唐艺昕','女','1984-1-7','144444444',3);


SELECT * FROM beauty;

#3.列的顺序可以颠倒,列和值的数量一定要匹配,可以省略列名

INSERT INTO beauty
VALUES(18,'张飞','男',NULL,'119',NULL,NULL);


#两种方式大pk

#1、方式一:支持插入多行;方式二:不支持
#2、方式一:支持子查询;方式二:不支持
insert into beauty(id,`name`,phone)
SELECT 26,'宋茜','11809866';


#二、修改语句 
/*

1.修改单表的记录
语法:
UPDATE 表明
SET 列=新值,...
WHERE 筛选条件

2.修改多表的记录【补充】

语法:
sql92语法:
update 表1 别名, 表2 别名
set 列=值...
WHERE 连接条件
AND 筛选条件;

sql99语法:
update 表明 别名
【inner left right】 join 表2 别名
on 连接条件
set 列=值...
WHERE 筛选条件;
*/

#案例1:修改beauty表中姓唐的女神的电话为13899888899

UPDATE beauty
SET phone = '13899888899'
WHERE `name` LIKE '唐%';

#2.修改多表的记录

#案例1:修改张无忌的女朋友的手机号为115

UPDATE beauty b
INNER JOIN boys bo
ON b.boyfriend_id = bo.id
set phone='115'
WHERE b.boyfriend_id = 1;


#案例2:修改没有男朋友的女神的男朋友编号都为2号

UPDATE boys
SET boyName = '张飞',userCP =10
WHERE id = 2;

SELECT * FROM boys;

UPDATE beauty b
LEFT JOIN boys bo
ON b.boyfriend_id = bo.id
SET b.boyfriend_id = 2
WHERE b.boyfriend_id IS NULL;

#删除语句
/*
方式一: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
语法:truncate table 表名;
*/


#方式一:delete
#1.单表的删除
#案例1:删除手机号以9结尾的女神信息

DELETE FROM beauty WHERE phone LIKE '%9';

#2.多表删除
#案例:删除张无忌女朋友的信息

delete b
FROM beauty b
JOIN boys bo
ON b.boyfriend_id = bo.id
WHERE b.boyfriend_id = 1;


#方式二:truncate

#案例:将魅力值>100的男神信息删除

TRUNCATE TABLE boys WHERE userCP >100;

#delete pk truncate

/*

1.delete 可以加where 条件,truncate不能加
2.truncate删除,效率高一丢丢
3.假如要删除的列表中有自增长列,如果用delete删除后,再插入数据,自增长的值从断点开始,而truncate删除后,再插入数据,自增长列的值从1开始。
4.truncate没有返回值,delete有
5.truncate删除不能回滚,delete删除可以回滚
*/

DDL语句

#DDL
/*
数据定义语言

库和表的管理

一、库的管理
创建、修改、删除
二、表的管理
创建、修改、删除

创建:create
修改:alter
删除:drop

*/

#一、库的管理
#1、库的创建

/*

语法:
create database 库名;




*/

#案例:创建库books;

create DATABASE IF NOT exists books;

#2、库的修改

#更改库的字符集

ALTER DATABASE books CHARACTER SET gbk;

#3、库的删除
Drop DATABASE books;


#二、表的管理
#1.表的创建


/*
create table 表名(
				列名 列的类型【(长度) 约束】,
				列名 列的类型【(长度) 约束】,
				列名 列的类型【(长度) 约束】,
				...
				列名 列的类型【(长度) 约束】
)


*/


#案例:创建表Book
Create database books;

Create table Book(
						id INT,
						bname VARCHAR(20),
						price DOUBLE,
						authorid INT,
						publishdate VARCHAR(20)
						
						
);



#表的修改
/*
语法:
ALTER TABLE 表名 add|CHANGE|MODIFY|DROP column 列名 【列类型 约束】


*/

#1.修改列名

ALTER TABLE BOOK CHANGE COLUMN PUBLISHDATE PD VARCHAR(20);

DESC BOOK;
#2.修改列的类型或约束
ALTER TABLE BOOK MODIFY COLUMN PD TIMESTAMP;

#3.添加新列
ALTER TABLE BOOK ADD COLUMN ANNUAL DOUBLE;

#4.删除列
ALTER TABLE BOOK DROP COLUMN ANNUAL;
#5.修改表名

ALTER TABLE BOOK RENAME TO BOOKK;


#3、表的删除

DROP TABLE book;


#通用写法

DROP DATABASE IF EXISTS 旧库名;

CREATE DATABASE 新库名;

DROP TABLE IF EXISTS 旧表名;
CREATE table 新表名;

#4.表的复制
create TABLE author(
						id INT, 
						an_name varchar(20),
						nation VARCHAR(20)



);
Insert into author VALUES
(1,'村上春树','日本'),
(2,'莫言','中国'),
(3,'冯唐','中国'),
(4,'金庸','中国');

SELECT * FROM AUTHOR;

#1.复制表的结构
create table copy like author;

#2.复制表的结构和数据
create TABLE copy2
SELECT * from author;

#仅仅复制某些关键字段

create table copy3
SELECT id,an_name
FROM author
WHERE 0;

常见类型

#常见的数据类型
/*
数值型:
				整形
				小数:
							定点数
							浮点数
字符型:
				较短的文本:char、varchar
				较长的文本:text、blob
				
				
日期型:
				
				

*/

#一、整型:

/*
分类:
	TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT
	1        2         3          4         8
	
特点:
1.如果不设置无符号,默认为有符号
2.如果要插入无符号,需要添加 UNSIGNED
3.如果插入的数值超出值的范围,默认插入的值就会是临界值
4.如果不设置长度,会有默认的长度,要想使宽度有效必须要搭配zerofill,如果插入的值长度不够就会用0去填充
*/

#1.如何设置无符号和有符号

CREATE TABLE tab_int(
								t1 INT,
								t2 INT UNSIGNED


);

desc tab_int;

# 二、小数

/*

1.浮点型
float(M,D)
double(M,D)
2.定点数类型
DEC(M,D)
DECIMAL(M,D)

特点:
1.
M:代表整数部位和小数部位
D:代表小数部位
如果超出范围插入临界值

2.M,D省略的话,如果是decimal M默认为10,D默认为0

3.DEC的精度更高

*/


#原则:
/*
所选的类型值越简单越好


*/

#三、字符型
/*
较短的文本:
char(M) 死板 效率高些
varchar(M) 可变
M:字符数

较长的文本:
text
blob(较大的二进制)

*/

#四、日期型
/*
分类:
date只保存日期
time只保存时间
year只保存年

datetime 保存日期+时间
timestamp 保存日期+时间

特点:

					      字节  				范围				时区等的影响
datetime        8             1000-9999   不受
timestamp       4							1970-2038   受
*/
# 进阶9 : 联合查询

/*

union : 将多条查询语句的结果合并成一个结果

语法:
查询语句1
union
查询语句2
union
查询语句3
union
...

特点:
1.要求多条查询的语句列数一致
2.要求多条查询语句每一列的类型和顺序一样
3.会自动去重,union all会包含重复项
*/


# DML语言
/*
数据操作语言:
插入:insert
修改:update
删除:delete
*/


# 一、插入语句
/*
语法:
方式1:
insert into 表名(列名,...,...) 
values(值1,...,); 

方式2:
insert into 表名
set 列名=value, 列名=value,...,
*/

# 二、修改语句
/*
语法
update 表名
set 列=new_value,..,
WHERE ...;
*/


# 三、删除语句
/*

方式一:
DELETE FROM 表名 WHERE 筛选条件

方式二:
truncate table 表名;


*/
# 1.查询工资最低的员工信息
SELECT * FROM employees 
WHERE salary = (
SELECT MIN(salary) FROM employees
);

# 2.查询平均工资最低的部门信息
SELECT * FROM departments WHERE department_id = 
(SELECT department_id FROM employees ORDER BY AVG(salary) LIMIT 1
);
# 3.查询平均工资最低的部门信息和该部门的平均工资
SELECT d.*, avgg.ag FROM departments d INNER JOIN(

SELECT AVG(salary) ag,department_id FROM employees GROUP BY department_id ORDER BY AVG(salary) LIMIT 1
) avgg on d.department_id = avgg.department_id;

# 4.查询平均工资最高的job信息

SELECT * FROM jobs WHERE job_id =(
SELECT job_id FROM employees GROUP BY job_id ORDER BY AVG(salary) DESC LIMIT 1);
# 5.查询平均工资高于公司平均工资的部门有哪些
SELECT department_id, AVG(salary) 平均工资 FROM employees GROUP BY department_id HAVING 平均工资 >
(
	SELECT AVG(salary) FROM employees
);
# 6.查询出公司中所有manager的详细信息
SELECT * FROM employees WHERE employee_id =any
(
	SELECT manager_id FROM employees
);
# 7.各部门中最高工资最低的那个部门的最低工资是多少
SELECT MIN(salary) FROM employees WHERE department_id =(

SELECT department_id FROM employees GROUP BY department_id ORDER BY MAX(salary) DESC LIMIT 1
);

# 8.查询平均工资最高的部门的manager的详细信息:last_name,department_id,email,salary
SELECT last_name,department_id email, salary FROM employees WHERE department_id = (
SELECT department_id FROM employees GROUP BY department_id ORDER BY AVG(salary) DESC LIMIT 1) AND 
manager_id IN (
SELECT manager_id FROM employees WHERE department_id  = (SELECT department_id FROM employees GROUP BY department_id ORDER BY AVG(salary) DESC LIMIT 1)
)
;





# 进阶9 : 联合查询

/*

union : 将多条查询语句的结果合并成一个结果

语法:
查询语句1
union
查询语句2
union
查询语句3
union
...

特点:
1.要求多条查询的语句列数一致
2.要求多条查询语句每一列的类型和顺序一样
3.union all会包含重复项
*/

SELECT last_name FROM employees E
UNION
SELECT job_title FROM jobs J;

# DML语言
/*
数据操作语言:
插入:insert
修改:update
删除:delete
*/

# 一、插入语句
/*
语法:
方式1:
insert into 表名(列名,...,...) 
values(值1,...,); 

方式2:
insert into 表名
set 列名=value, 列名=value,...,
*/

# 二、修改语句
/*
语法
update 表名
set 列=new_value,..,
WHERE ...;
*/


# 三、删除语句
/*

方式一:
DELETE FROM 表名 WHERE 筛选条件

方式二:
truncate table 表名;


*/

USE myemployees;

CREATE TABLE my_employees(
	id INT(10),
	First_name VARCHAR(10),
	Last_name VARCHAR(10),
	Userid VARCHAR(10),
	Salary DOUBLE(10,2)
);

CREATE TABLE users(
	id INT,
	userid VARCHAR(10),
	department_id INT
);


INSERT INTO my_employees
VALUES(1,'patel','Ralph','Rpatel',895)
,(2,'Dancs','Betty','Bdancs',860)
,(3,'Biri','Ben','Bbiri',1100)
,(4,'Newman','Chad','Cnewman',750)
,(5,'Ropeburn','Audrey','Aropebur',1550);



/*
DDL语言
数据定义语言
库和表的创建

一、库的管理
创建、修改、删除
二、表的管理
创建、修改、删除

创建:create
修改:alter
删除:drop

*/

# 一、库的管理
#1、库的创建

/*

语法:create database 库名

*/

# 案例
CREATE database IF NOT EXISTS books;

#2、库的修改

RENAME DATABASE books to 


# 表的修改
ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;

# 修改列的类型
ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;


# 常见的数据类型
/*
数值型:
			整型
			小数:
						定点数
						浮点数
字符型:
			较短的文本:char,varchar
			
*/

# 一、整型
/*
分类:
tinyint, Smallint,mediumnt,int/integer,bigint
1        2        3        4           8
 

*/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值