# 起别名 SELECT name AS my_name # 第一种方式 FROM students;
SELECT name my_name # 第二种方式 FROM students;
去重
1 2 3 4
SELECT DISTINCT name FROM students;
字段拼接
1 2 3 4 5
MySQL中的'+'号只能作为运算符 SELECT CONCAT(last_name,first_name) AS name FROM students;
条件查询
语法
1 2 3 4 5 6
SELECT 查询列表 FROM 表名 WHERE 筛选条件;
逻辑运算符
1 2 3 4 5 6 7 8 9 10
&& 等价于AND || 等价于OR !等价于NOT # 从students表中选取id在10到20之间的学生的name(开区间) SELECT name FROM students WHERE id > 10 AND id < 20;
模糊查询
like
1 2 3 4 5 6 7 8 9 10 11 12
通配符:% 任意多个字符 _ 任意单个字符 转义字符: '\_' '\%' '&_' ESCAPE '&' (&可为任意符号) # 从students表中查询name字段中第三个为A,第五个为_,第六个为%的学生 SELECT * FROM students WHERE name LIKE '__A_\_\%%'; # 等价于 name LIKE '__A_$_$%%' ESCAPE '$';
between a and b
1 2 3 4 5 6 7 8 9 10
# 从students表中查询id在100到120之间的学生信息(闭区间) SELECT * FROM students WHERE id BETWEEN 100 ADN 120; # 等价于 id >=100 AND id <=120; 1、BETWEEN AND是闭区间 2、a表达式必须<=b表达式
in
1 2 3 4 5 6 7 8
# 从students表中查询id为60,70,80,90的学生信息 SELECT * FROM students WHERE id IN ('60','70','80','90'); # 等价于 id = '60' OR id = '70' OR id = '80' OR id = '90';
is null
1 2 3 4 5 6 7 8 9 10
# 从students表中查询id不存在的学生信息 SELECT * FROM students WHERE id IS NULL; # 等价于id <=> NULL # <=>安全等于 <>安全不等于 # mysql中不能用id = NULL判断
排序查询
语法
1 2 3 4 5 6 7 8 9
SELECT 查询列表 FROM 表名 (筛选条件) ORDER BY 排序列表 (ASC|DESC) # 默认ASC升序 排序列表可以是单个字段、多个字段、表达式、函数、别名等
在分组查询后用having关键词取代where # 案例5:查询哪个部门的员工个数>2 SELECT COUNT(*),department_id FROM employees GROUP BY department_id HAVING COUNT(*)>2;
# 案例6:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资 SELECT MAX(salary),job_id FROM employees GROUP BU job_id HAVING MAX(salary)>12000;
# 案例7:查询领导编号>102的每个领导手下的员工最低工资>5000的领导编号,以及其最低工资 SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000
按表达式或函数分组
1 2 3 4 5
# 案例8:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数大于5的有哪些 SELECT COUNT(*) FROM employees GROUP BY LENGTH(last_name) HAVING COUNT(*)>5;
按多个字段分组
1 2 3 4 5
# 案例9:查询每个部门每个工种的员工的平均工资 SELECT AVG(salary),department_id,job_id FROM employees GROUP BY department_id,job_id; #将department_id和job_id一致的分成一组
添加排序
1 2 3 4 5
# 案例10:查询每个部门每个工种的员工的平均工资,并且按平均工资降序显示 SELECT AVG(salary),department_id,job_id FROM employees GROUP BY department_id,job_id ORDER BY AVG(salary) DESC;
# 案例1:查询女生名和对应的男生名 SELECT girl_name,boy_name FROM boys,girls WHERE girls.boyfriend_id=boys.id; # 用表名限定字段 # 表的先后顺序没有要求
# 案例2:查询员工名和对应的部门名 SELECT name,department_name FROM employees,departments WHERE employees.department_id=departments.id;
# 案例3:查询员工名,工种号,工种名 SELECT name,e.job_id,job_name FROM employees e,jobs j WHERE e.job_id=j.id; # 为表起别名,起了别名后不能再用原名
# 添加筛选 # 案例4:查询有奖金的员工名、部门名 SELECT name,department_name FROM employees e, departments d WHERE e.department_id=d.id AND e.commission_pct IS NOT NULL
# 案例5:查询位置名中第二个字符为o的部门名和位置名 SELECT department_name, location_name FROM departments d, locations l WHERE d.location_id=l.location_name AND l.location_name LIKE '_o%'
# 添加分组 # 案例6:查询每个城市的部门个数和城市名 SELECT COUNT(*),city FROM departments d, citys c WHERE d.city_id=c.id; GROUP BY city;
# 案例7:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资 SELECT department_name, d.manager_id, MIN(salary) FROM departments d, employees e WHERE e.department_id=d.id AND commission_pct IS NOT NULL GROUP BY department_name, d.manager_id;
# 添加排序 # 案例8:查询每个工种的工种名和员工的个数,并且按员工个数降序 SELECT job_name, COUNT(*) FROM jobs j, employees e WHERE e.job_id=j.id GROUP BY job_name ORDER BY COUNT(*) DESC
# 实现三表连接 # 案例9:查询员工名、部门名和所在的城市 SELECT name,department_name, city FROM employees e, departments d, citys c WHERE e.department_id=d.id AND d.city_id=c.id
非等值连接
1 2 3 4
# 案例1:查询员工的工资和工资级别 SELECT salary, grade_level FROM employees e, job_grades g WHERE salary BETWEEN g.lowest_sal AND g.highest_sal;
自连接
1 2 3 4 5
把一张表当作多张表来用 # 案例1:查询员工名和上级的名称 SELECT e.name, m.name FROM employees e, employees m WHERE e.manager_id=m.employee_id;
# 案例1:查询员工名、部门名 SELECT name, department_name FROM employees e INNER JOIN departments d ON e.department=d.id;
# 添加筛选 # 案例2:查询名字中包含e的员工名和工种名 SELECT name, job_name FROM employees e INNER JOIN jobs j ON e.job_id=j.id WHERE name LIKE '%e%';
# 添加分组 # 案例3:查询部门个数>3的城市名和部门个数 SELECT city_name, COUNT(*) FROM departments d INNNER JOIN citys c ON d.city_id=c.city_name GROUP BY c.city_name;
# 添加排序 # 案例4:查询员工个数>3的部门名和员工个数,并按个数降序 SELECT department_name, e.COUNT(*) FROM department d INNER JOIN employees e ON e.department_id=d.id HAVING e.COUNT(*)>3 GROUP BY department_name ORDER BY e.COUNT(*) DESC;
# 三表连接 # 案例5:查询员工名、部门名、工种名并按部门名降序 SELECT name, department_name, job_name FROM employees e INNER JOIN departments d ON e.department_i=d.id INNER JOIN jobs j ON e.job_id=j.id ORDER BY department_name DESC;
非等值连接
1 2 3 4 5
# 案例1:查询员工的工资级别 SELECT salary, grade_level FROM employees e JOIN job_grades g ON e.salary BETWEEN g.lowest_sal AND g.highest_sal;
自连接
1 2 3 4 5
# 案例1:查询员工的名字、上级的名字 SELECT e.name, m.name FROM employees e JOIN employees m ON e.manager_id=m.id;
# 案例1:谁的工资比Abel高 SELECT * FROM employees WHERE salary>( SELECT salary FROM employees WHERE name='Abel' );
# 案例2:返回job_id与141号员工相同,salary 比143号员工多的员工 姓名,job_id和工资 SELECT name, job_id, salary FROM employees e WHERE e.job_id=( SELECT job_id FROM employees WHERE employee_id=141 ) AND salary>( SELECT salary FROM employees WHERE employee_id=143 );
特点: 1、返回多行 2、需要配合多行比较操作符来使用: in/not in any/some all # 案例1:返回loaction_id是1400或1700的部门中的所有员工姓名 select name from employees where department_id in( select distinct department_id from department where location_id in(1400,1700) );
# 案例2:返回其它工种中比job_id为`IT_PROG`工种所有员工的工资都要低的员工的员工号、姓名 select id,name from employees where salary < all( # min select distinct salary from employees where job_id = 'IT_PROG' ) and job_id != 'IT_PROG';
行子查询
1 2 3 4 5 6 7 8
特点:返回一行多列 # 案例1:查询员工编号最少并且工资最高的员工信息 select * from employees where (employee_id,salary)=( select min(employee_id),max(salary) from employees );
select后面
1 2 3 4 5 6 7 8
特点:只支持一行一列(标量子查询) # 案例1:查询每个部门的员工的个数 select e.*,( select count(*) from employees e where e.department_id=d.department_id ) 个数 from department d;
from后面
1 2 3 4 5 6 7 8 9 10 11
特点:将select返回的结果当作表(数据源)来使用 必须起别名 # 案例1、查询每个部门的平均工资的工资等级 select ag_dep.*, grade.level from( select avg(salary) ag ,department_id from employees group by department_id ) ag_dep inner join job_grades g on ag_dep.ag between lowest_sal and highest_sal;
exists后面(相关子查询)
1 2 3 4 5 6 7 8 9 10 11
exists语法: exists(完整的查询语句) 结果:1或0 # 案例1:查询有员工的部门名 select department_name from departments d where exists( select * from employees e where d.department_id=e.department_id );
select 查询列表 from 表1 [join type join 表2 on 连接条件 where 筛选条件 group by 分组字段 having 分组后的筛选 order by 排序的字段] limit 分页语句; limit后分页条件有两种: 1、limit后跟着两个数字(只有一个数字时默认第一个数字为0): limit 1,3; 表示查询3条数据,跳过1条数据(即查询2,3,4) 2、limit和offset关键字组合使用: limit 5 offset 4; 表示查询5条数据,跳过4条(即查询5,6,7,8,9)
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 案例1:查询前五条员工信息 select * from employees limit 0,5; select * from employees limit 5;
# 案例2:查询第11条到第25条 select * from employees limit 10,15;
# 案例3:查询有奖金的前十名员工的信息 select * from employees where commission_pct is not null order by salary desc limit 10;
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...) BEGIN 存储过程体 END
delimiter 命令:
在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。为解决这个问题,通常可使用 DELIMITER 命令将结束命令修改为其他字符。在创建存储过程最后的 end 后写上修改的结束符,表示语句结束。
delimiter // 将结束符修改为//
delimiter ; 将结束符修改为;
例:创建不带参数的存储过程
1 2 3 4 5 6 7 8 9
mysql> delimiter // mysql> create procedure test() -> begin -> update t_user set c_name = "hello" where id = 1; -> end // mysql> delimiter ; # 调用存储过程 mysql> call test;
例:创建带参数的存储过程
1 2 3 4 5 6 7 8 9 10
mysql> delimiter // mysql> create procedure test -> (IN name varchar(30)) -> begin -> update t_user set c_name = name where id = 1; -> end // mysql> delimiter ; # 调用存储过程 mysql> call test('hello')
删除
1
mysql> drop procudure test;
查看
1 2 3 4 5
# 查看所有存储过程 mysql> show procedure status; # 查看指定存储过程 mysql> show procedure status like 存储过程名;