目录
安全等于:<=>;即可判断null,也可以判断普通数值,但可读性较低
4.mod:取余 mod(a,b)=a%b;逻辑a-a/b*b,符号于被除数一致
5.str_to_data():将字符通过指定的格式转换为日期
①if函数:if-else的效果,写法类似于三元运算符Q?A:B
1.基础查询
select 查询列表 from 表名;
类似于:System.ot.println(打印东西);
特点:
1.查询列表可以是:表中的字段、常量值、表达式、函数
2.查询的结果是一个虚拟的表格
查询表中的单个字段:
SELECT last_name FROM employees;
查询表中的多个字段:
SELECT last_name,salary,email FROM employees;
查询表中的所有字段:
SELECT
`employee_id`,#" ` "为着重号,用于区分字段和关键字
`first_name`,
`last_name`,
`email`,
`phone_number`,
`job_id`,`salary`,
`commission_pct`,
`manager_id`,
`department_id`,
`hiredate`
FROM
employees;
或
SELECT * FROM employees;
*查询时显示的顺序与表中的顺序一样,合理使用,可提高阅读性
查询常量值:
SELECT 100;
SELECT 'john';
查询表达式:
SELECT 100%98;
查询函数 :
SELECT VERSION();
起别名(AS):①便于理解
②如果查询的字段有重名的情况,使用别名可以区分开来
方式一:
SELECT 100%98 AS 结果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;
方式二:省略AS(效果同上)
SELECT last_name 姓,first_name 名 FROM employees;
注意:别名中如果包含关键字、特殊符号,一般使用 " "引起来
SELECT salary "out put" FROM employees;
去重:
案例:查询员工表中涉及到的所有的部门编号
SELECT DISTINCT department_id FROM employees;
+号的作用:
Java中+的作用:
①运算符②连接符
MySQL中+的作用:
仅仅只有运算符
SELECT 100+90;#两个操作数都为数值型,则做加法运算
SELECT '123'+90;#一个为字符型,则试图将字符型数值转换为数值型
#若成功,则继续做加法运算
#若失败,则将字符型数值转换成0
SELECT 'john'+90;
SELECT NULL+10;#只要其中一方为null,则结果肯定为null
案例:查询员工名和姓连接成一个字段,并显示为 姓名
concat
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
ifnull()用于判空
2.条件查询
语法:select 查询列表 from 表名 where 筛选条件;(①表明②筛选条件③查询列表)类似于if()判断
①按条件表达式筛选:
条件运算符:> < =(==MySQL中不支持) <>(!=)
SELECT * FROM employees WHERE salary > 12000;
SELECT last_name,department_id FROM employees WHERE department_id <> 90;
②按逻辑表达式筛选:
逻辑运算符:and(&&) or(||) not(!)
作用:连接条件表达式
SELECT last_name,salary,commission_pct FROM employees WHERE salary > 10000 AND salary < 20000;
③模糊查寻:
like,一般配合通配符使用
通配符:
%:任意多个字符,包含0个字符
_:任意单个字符
案例1:查询员工名中包含字符a的员工信息
SELECT * FROM employees WHERE last_name LIKE '%a%';
案例二:查询员工名单中第三个字符为e,第五个字符为a的员工名和工资
SELECT last_name,salary FROM employees WHERE last_name LIKE '__n_l%';
案例三:查询员工名中第二个字符为_的员工名(使用转义符\,或关键字escape)
SELECT last_name FROM employees WHERE last_name LIKE '_\_%';
SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';
between and
①使用between and可以提高语句的简洁度
②包含临界值,between类似于>=,and类似于<=
③两个临界值不要调换顺序
案例一:员工编号在100-120之间的员工信息
SELECT
*
FROM
employees
WHERE
employee_id BETWEEN 100 AND 120;
in:判断某字段的值是否属于in列表中的某一项
特点:①提高语言简洁度
②in列表的值类型必须一致
案例:查询员工的工种编号是IT_PROF、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT last_name,job_id FROM employees WHERE job_id IN ('IT_PROT','AD_VP','AD_PRES');
is null:=或<>不能用于判断null值
is not null
案例:查询没有奖金的员工名和奖金率
SELECT last_name,commission_pct FROM employees WHERE commission_pct IS NULL;
SELECT last_name,commission_pct FROM employees WHERE commission_pct IS NOT NULL;
安全等于:<=>;即可判断null,也可以判断普通数值,但可读性较低
3.排序查询
语法:
select 查询列表3
from 表1
(where 筛选条件)2
order by 排序列表(asc升序/desc降序)4
案例一:查询员工信息,要求工资从高到低排序
select * from employees order by salary desc;
select * from employees order by salary;不加关键词,默认升序
案例二:查询部门编号>=90的员工信息,按入职时间的先后进行排序
select * from employees where department_id >= 90 order by hiredate asc ;
案例三:按年薪的高低显示员工的信息和年薪(按别名升序)
select *,salary*12*(1+ifnull(commission_pct,0)) as 年薪 from employees order by 年薪desc;
案例四:按姓名的长度显示员工的姓名和工资(按函数排序)
select concat(last_name,first_name) 姓名,length(last_name) 长度,salary from employees order by length(last_name) desc;
案例五:查询员工信息,要求先按工资排序,再按员工编号排序
select * from employees order by salary asc ,employee_id desc ;
特点:
①不写asc或desc时默认为asc
②order by子句中可以支持单个字段、多个字段、表达式、函数、别名
③order by子句一般是放在查询语句的最后面,limit除外
4.常见函数
一、字符类函数
1.upper()-->转大写,lower()-->转小写
2.substr,截取字符串(索引从1开始)
①截取从指定索引处后面的所有字符
SELECT SUBSTR('Microsoft Azure AI',8) 'out put';
②截取从指定索引处指定字符长度的字符
SELECT SUBSTR('Microsoft Azure AI',1,9) 'out put';
案例:名字中首字符大写,其他字符小写,用_拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),SUBSTR(last_name,2),'_',first_name) 姓名 FROM employees;
3.instr:返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR('Microsoft Azure AI','Azure') 'output';
4.trim:可以过滤指定的字符串
5.lpad:用指定字符实现左填充
SELECT LPAD ('Nahimic',10,'*');
6.rpad:用指定字符实现右填充
SELECT RPAD ('Nahimic',10,'*');
7.replace:替换
SELECT REPLACE('aaaaaaaabcaaaaaa','a','*');
二、数学函数
1.round:四舍五入
SELECT ROUND(1.65);-->2
SELECT ROUND(1.45);-->1
SELECT ROUND(3.14159265357989,10);
2.ceil:向上取整,返回>=该参数的最小整数
SELECT CEIL(1.0000000000001);-->2
SELECT CEIL(-1.0000000000001);-->-1
3.floor:向下取整,返回<=该参数的最大整数
SELECT FLOOR(9.9999999999);-->9
SELECT FLOOR(-9.9999999999);-->-10
3.truncate:截断,截取到小数点后第几位
SELECT TRUNCATE(1.65,1);
4.mod:取余 mod(a,b)=a%b;逻辑a-a/b*b,符号于被除数一致
三、日期函数
1.now:返回当前系统日期+时间
SELECT NOW();
2.curdate:返回当前系统日期,不包含时间
SELECT CURDATE();
3.curtime:返回当前系统时间,不包含日期
SELECT CURTIME();
4.或以获取指定的部分,年、月、日、小时、分、秒
yaer()、month()[monthtime()月名]月、···、基本为对应单词
5.str_to_data():将字符通过指定的格式转换为日期
SELECT * FROM employees WHERE hiredate = '1992-4-3';
SELECT DATE_FORMAT(NOW(),'%Y年%m月%d日');
data_format():将日期转换为字符
6.其他函数
version():查看数据库版本号
database():查看当前的数据库
user():当前用户
7.流程控制函数
①if函数:if-else的效果,写法类似于三元运算符Q?A:B
SELECT IF(10>5,'yes','no');
②case函数:
使用一:类似于Java中的switch-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倍,其他部门,显示原工资
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;
使用二:类似于Java中的多重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
案例:查询员工的工资情况,如果工资大于2w,显示A级别;如果工资大于1.5w,显示B级别;如果工资大于1w,显示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;
5.分组函数
功能:用作统计使用,又称为聚合函数或统计函数或组函数
分类:
sum求和、avg平均值、max最大值、min最小值、count计算个数
1.简单 的使用
select sum(salary) from employees;
2.特点:
①sum、avg一般用于处理数值型;max、min、count可以处理任何类型
②以上的的分组函数都忽略null值(null + 任何值 = null)
③可以和distinct搭配使用可实现去重的运算
3.和分组函数一同查询的字段有限制
6.分组查询 group by
语法:
select 分组函数,列(要求出现在group by的后面)
from 表
[where 筛选条件]
group by 分组的列表
[order by 子句]
注意:查询列表必须特殊,要求是分组函数和group 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;
添加复杂的筛选条件 关键字:having(放在group by 和 order by 之间)
案例一:查询哪个部门的员工个数大于2
①先查询每个部门的员工个数:
SELECT COUNT(*),department_id FROM employees GROUP BY department_id;
②根据①的结果进行筛选,查询哪个部门的员工个数>2
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
案例三:查询领导领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
SELECT
MIN (salary),
manager_id
FROM
employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN (salary) > 5000;
特点:
①分组查询中的筛选条件分为两类
分组前筛选(数据源:原始表)(group by子句前)(where)
分组后筛选(数据源:分组后的结果集)(group by子句后)(having)
②group by字句支持单个字段分组,多个字段分组(多个字段之间用,隔开没有顺序要求),表达式或函数用的较少
③也可以添加排序
-分组函数做条件肯定是放在having子句中
-能用分组前筛选的,就优先考虑使用分组前筛选
按表达式或函数分组
案例:按员工姓名的长度分组,查询每一组的员工人数,筛选员工数>5的有哪些
SELECT
COUNT(*),LENGTH(last_name) len_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),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id
ORDER BY
AVG(salary) DESC;
7.连接查询(多表查询)
含义:当查询的字段来自多个表时,就会用到连接查询
笛卡尔乘积现象:表一 m行。表二 n行,结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
表.字段 --> 类似于Java中的 类名.属性
select name,boyName from beauty,boys where beauty.boyfriend_id=boys.id;
分类:
·按年代分类:1)sql92标准(仅仅支持内连接)、2)sql99标准(推荐)
·按功能分类:
1)内连接:①等值连接、②非等值连接、③自连接
2)外连接:①左外连接、②右外连接、③全连接
3)交叉连接
一、sql92标准
1.等价连接
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面学习的所有子句使用
案例一:查询员工名和对应的部门名
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE employees.`department_id` = departments.`department_id`;
1)为表起别名
提高语言简洁度,区分多个重名的字段
注意:如果为表起了别名,则查询的字段不能使用原来的表名限定
案例:查询员工名,工种号,工种名
SELECT
last_name,
e.job_id,
job_title
FROM
employees e,
jobs j
WHERE e.`job_id` = j.`job_id`;
2)两个表的顺序可以调换
3)多个筛选条件之间加and
案例一:查询有奖金的员工名、部门名
SELECT
last_name,
department_name,
commission_pct
FROM
employees e,
departments d
WHERE e.department_id = d.department_id
AND e.commission_pct IS NOT NULL;
案例二:查询城市名中第二个字符为o的部门名和城市名
SELECT
city,
department_name
FROM
locations l,
departments d
WHERE l.`location_id`=d.`location_id` 连接条件为两个表中所共有的字段
AND l.`city` LIKE '_o%';
4)可以加分组
案例:查询每个城市的部门个数
select count(*),city from locations l,departments d where d.location_id=l.location_id group by city;
案例二:查询有奖金的每个部门的部门名和部门领导编号和部门的最低工资
SELECT
department_name,
d.manager_id,
MIN (salary)
FROM
departments d,
employees e
WHERE d.department_id = e.department_id
AND commission_pct IS NOT NULL
GROUP BY department_name,d.manager_id;
5)可以加排序
案例一:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT
COUNT (*),
j.job_title
FROM
employees e,
jobs j
WHERE j.job_id = e.job_id
GROUP BY j.job_title
ORDER BY COUNT (*) 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.非等值连接
案例一:查询员工的工资和工资级别
SELECT
salary,
grade_level
FROM
employees e,
job_grades j
WHERE e.salary BETWEEN j.lowest_sal
AND j.highest_sal;
3.自连接
把原本一张表的内容在逻辑上当作多张表进行查询
案例:查询员工名和上级的名称
select e.last_name, e.employee_id, m.last_name, m.employee_id
from employees e,
employees m
where e.employee_id = m.employee_id;
二、sql99标准
语法:
select 查询列表
from 表1 别名 (连接类型)
join 表2 别名
on 连接条件
(where 筛选条件)/(group by 分组)/(having 筛选条件)/(order by 排序列表)
连接类型分类:
内连接*:inner
1.等值连接:和sql92中的等值连接效果相同 join ... on ......
案例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 e.job_id = j.job_id
where last_name like '%e%';
案例3:查询部门个数>3的城市名和部门个数(添加分组+筛选)
select count(*) 部门个数, city
from locations l
inner join departments d on l.location_id = d.location_id
group by city
having count(*) > 3;
案例4:查询哪个部门的员工数>3的部门的员工名和员工个数,并按个数降序(添加排序)
select count(*) 员工个数, department_name
from departments d
inner join employees e on d.department_id = e.department_id
group by department_name
having count(*) > 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 j.job_id = e.job_id
order by department_name desc;
2.非等值连接:
案例:查询员工的工资和工资级别
select salary, grade_level
from employees e
join job_grades jg on e.salary between jg.lowest_sal and jg.highest_sal;
3.自连接:
案例:查询员工名和上级的名称
select e.last_name, m.last_name
from employees e
join employees m on e.manager_id = m.employee_id;
外连接:
应用:用于查询一个表有,另一个表没有的记录
特点:①外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配值;如果从表里没有和它匹配的,则显示null
外连接查询结果=内连接结果 + 主表中有从表里没有的记录
②左外连接:left join左边的是主表;右外连接:right join右边的是主表
③左外和右外交换两个表的顺序,可以实现相同的效果
-左外*:left (outer)
-右外*:right (outer)
-全外:full (outer)
交叉连接:cross,类似于笛卡尔乘积
SELECT b.*,bo.* FROM beauty b CROSS JOIN boys bo;
8.子查询
含义:出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
按照子查询的出现位置:
①select后面 仅支持标量子查询
②from后 支持表子查询
③ where或having后 标量、列、行子查询
④exists后(相关子查询)
按结果集的行列数不同:
①标量子查询(结果集只有一行一列)
②列子查询(结果集只有一列多行)
③行子查询(结果集只有一行多列)
④表子查询(结果集一般为多行多列)
一、where或having后面
①标量子查询(单行子查询)
案例:谁的工资比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, salary, job_id
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:返回公司工资最少的与员工的姓名,job_id和工资
select last_name, job_id, salary
from employees
where salary = (
select min(salary) from employees
);
案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
select min(salary),department_id
from employees
group by department_id
having min(salary)>(
select min(salary)
from employees
where department_id=50
);
非法使用标量子查询:
子查询返回结果不唯一,或者返回结果为空值的
②列子查询(多行子查询)
一般搭配多行操作符使用(in / not in / any / some / all);
案例1:返回location_id是1400或者是1700的部门中的所有员工姓名
select last_name
from employees
where department_id in (
select distinct department_id
from departments
where location_id in(
1400,1700
)
);
案例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';
③行子查询(多列多行)
特点:子查询放在小括号内;子查询一般放在条件的右侧;标量子查询,一般搭配单行操作符使用(> < >= <= = <>);子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
案例1:查询员工编号最小并且工资最高的员工信息
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 e
where e.department_id=d.department_id
)
from departments d;
案例2:查询员工号=102的部门名
select (
select department_name
from departments d
join employees e on d.department_id = e.department_id
where employee_id = 102
)部门名;
三、from后面
将子查询结果充当一张表,要求必须起别名
案例:查询每个部门平均的工资等级
select ag_dep.*,j.grade_level
from (
select avg(salary) ag,department_id
from employees
group by department_id
) ag_dep
inner join job_grades j
on ag_dep.ag between lowest_sal and highest_sal;
四、exists后面(相关子查询)
exists(完整的查询语句),结果为0、1
案例:查询有员工的部门名
select department_name
from departments d
where exists(
select *
from employees e
where e.department_id=d.department_id
);
9.分页查询
应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
(join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序字段)
limit offset(要显示条目的起始索引,索引从0开始),size(要显示的条目个数)
案例:查询前五条员工信息
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;
特点:
①limit子句放在查询语句的最后
②公式(要显示的页数page,每页的条目数size):limit (page - 1) * size , size;
10.union联合查询(union关键词)
合并:将多条查询语句的结果合并成一个结果
引入案例:查询部门编号> 90或邮箱中包含a的员工信息
select * from employees where email like '%a%' or department_id > 90;
||
select * from employees where email like '%a%'
union
select * from employees where department_id > 90;
语法:
查询语句1
union
查询语句2
union
查询语句3...(无限套娃)
应用场景:要查询的结果来自多个表,且多个表没有直接的连接关系,但查询的信息一致时
特点:
①要求多条查询与语句的查询列数是一致的
②要求多条查询语句的查询的每一列的类型和顺序最好是一致的
③union关键字默认是去重的,如果使用 union all 可以包含重复项