一、DQL语言语法顺序
⑦select 查询列表
①from 表1
②left/right/inner join 表2
③on 连接条件
④where 筛选条件
⑤group by 分组列表
⑥having 分组后进行筛选
⑧order by 排序列表
⑨limit 起始索引数,条目数
二、基础查询
1.打开指定库
USE myemployees;
2.查询单个字段
SELECT last_name FROM employees;
3.查询多个字段
SELECT last_name,salary,email FROM employees;
4.查询所有字段
SELECT * FROM employees;
5.查询常量
SELECT 100;
SELECT 'john';
6.查询表达式
SELECT 100*98;
7.查询函数
SELECT VERSION();
8.起别名
用as起别名/直接空格 别名
SELECT 100%98 AS 结果;
SELECT 110%23 结果;
9.去重DITINCT
SELECT DISTINCT department_id FROM employees;
10.+号的作用:做加法运算
SELECT last_name+first_name AS 姓名 FROM employees;
select 数值+数值: 直接运算
select 字符+数值:先试图将字符转换成数值,如果转换成功,继续运算;否则转换成0,再做运算
select null+值;结果都为null
11.CONCAT(str1,str2,...)函数:拼接字符
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
12.ifnull函数
功能:判断某字段或表达式是否为null,如果为null 返回指定的值,否则返回原本的值
select ifnull(commission_pct,0) from employees;
13.isnull函数
功能:判断某字段或表达式是否为null,如果是,则返回1,否则返回0
三、条件查询
1、按条件表达式筛选
> < = <> != >= <= <=>安全等于
#案例一:查询员工工资大于一万二的员工信息
SELECT * FROM employees WHERE salary>12000;
#案例二:查询部门编号不等于90号的员工名和部门编号
SELECT last_name,department_id FROM employees WHERE department_id<>90;
2、按逻辑表达式筛选
作用:用于连接条件表达式
&& and:如果两个条件都为真,结果为真;反之为假
|| or:只要有一个条件为真,结果为真;反之为假
! not:如果连接条件本身为假,结果为真;反之为假
#案例一:查询工资在一万到两万之间的员工名、工资以及奖金
SELECT last_name,salary,commission_pct FROM employees WHERE salary>10000 and salary <20000;
#案例二:查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT * FROM employees WHERE department_id<90 or department_id>110 or salary>15000;
SELECT * FROM employees WHERE NOT (department_id>=90 and department_id<=110) OR salary>15000;
3.模糊查询
(1)like
like:一般搭配通配符使用,可以判断字符型或数值型
通配符:%任意多个字符(包含0个字符),_任意单个字符
#案例一:查询员工名中包含字符a的员工信息
SELECT * FROM employees WHERE last_name LIKE '%a%';
#案例二:查询员工名中第三个字符为e,第五个字符为a的员工名和工资
SELECT last_name,salary FROM employees WHERE last_name LIKE '__n_l%';
#案例三:查询员工名中第二个字符为_的员工名
SELECT last_name FROM employees WHERE last_name LIKE '_\_%';
SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';
4.BETWEEN AND
#案例一:查询员工编号在100到120之间的员工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
5.IN
#案例一:查询员工的工种编号是IT_PROT、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT last_name,job_id FROM employees WHERE job_id IN ('IT_PROT','AD_VP','AD_PRES');
6.is NULL
#案例一:查询没有奖金的员工名和奖金率
SELECT last_name,commission_pct FROM employees WHERE commission_pct IS NULL;
7.安全等于 <=>
#案例一:查询没有奖金的员工名和奖金率
SELECT last_name,commission_pct FROM employees WHERE commission_pct <=>NULL;
#案例二:查询工资为12000的员工信息
SELECT * FROM employees WHERE salary <=>12000;
四、排序查询
order by 排序列表 ASC/DESC
升序后跟ASC或不写;降序后跟DESC
#案例一:查询员工信息,要求工资从高到低排序
SELECT * FROM employees ORDER BY salary DESC;
#案例二:查询部门编号大于等于九十的员工信息,按入职时间的先后进行顺序
SELECT * FROM employees WHERE department_id>=90 ORDER BY hiredate;
#案例三:按年薪的高低显示员工的信息和年薪【按表达式排序】
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 LENGTH(last_name),last_name,salary FROM employees ORDER BY LENGTH(last_name) DESC;
#案例六:查询员工信息,先按工资升序排序,再按员工编号降序排序【按多个字段排序】
SELECT * FROM employees ORDER BY salary,employee_id DESC;
五、常规函数
1.字符函数
(1)LENGTH(str)获取参数值的字节个数
SELECT LENGTH(str)
(2)CONCAT(str1,str2,...) 拼接字符
SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
(3)UPPER(str) ,LOWER(str)
SELECT UPPER('john');//使小写字符变大写字符
SELECT LOWER('JOHN');//使大写字符变小写字符
SELECT CONCAT(UPPER(first_name),LOWER(last_name)) 姓名 FROM employees;
(4)SUBSTR(str FROM pos FOR len)截取子串
#索引从1开始
#截取从指定索引处后面所有字符
SELECT SUBSTR('李莫愁爱上了陆展元',7) out_put;
#截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了陆展元',1,3) out_put;
#案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) out_put FROM employees;
(5)INSTR(str,substr)返回字串第一次出现的索引,如果找不到返回0
SELECT INSTR('杨不悔爱上了殷六侠','殷六侠') AS out_put;
(6)TRIM([remstr FROM] str)去前后空格,把remstr改成想改的也可以去掉
SELECT TRIM(' 张翠山 ') AS out_put;
SELECT TRIM('a' FROM 'aaaaaaaaaaaaaaa张翠山aaaaaaaaaa') AS out_put;
(7)LPAD(str,len,padstr) 用指定的字符实现左填充指定长度
SELECT LPAD('殷素素',10,'*') AS out_put;
(8)RPAD(str,len,padstr) 用指定的字符实现右填充指定长度
SELECT RPAD('殷素素',10,'*') AS out_put;
(9)REPLACE(str,from_str,to_str) 替换
SELECT REPLACE('张无忌爱上了周芷若','周芷若','赵敏') AS out_put;
2.数学函数
(1)ROUND(X)四舍五入
SELECT ROUND(1.45);
SELECT ROUND(1.567,2);
(2)CEIL(X)向上取整,返回大于等于该参数的最小整数
SELECT CEIL(2.4);
(3)FLOOR(X)向下取整,返回小于等于该参数的最大整数
SELECT FLOOR(2.4);
(4)TRUNCATE(X,D)截断
SELECT TRUNCATE(1.69999,1);
(5)MOD(N,M)取余
SELECT MOD(10,3);
3.日期函数
(1)NOW() 返回当前系统日期+时间
SELECT NOW();
(2)CURDATE() 返回当前系统日期,不包含时间
SELECT CURDATE();
(3)CURTIME()返回当前时间,不包含日期
SELECT CURTIME();
#可以获取指定的部分,年、月、日、小时、分钟
SELECT YEAR(NOW()) 年;
SELECT MONTH(NOW()) 月;
SELECT DAY(NOW()) 日;
(4)STR_TO_DATE(str,format) 将字符通过指定的格式转换成日期
SELECT STR_TO_DATE('1998-3-3','%Y-%c-%d') AS out_put;
#案例:查询入职日期为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');
(5)DATE_FORMAT(date,format)将日期转换为字符
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;
#案例:查询有奖金的员工名和入职日期(月/日 年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %Y年') FROM employees WHERE commission_pct IS NOT NULL;
4.其他函数
SELECT VERSION();
SELECT DATABASE();
SELECT USER();
5.流程控制函数
(1)IF(expr1,expr2,expr3) IF ELSE 的效果
SELECT IF(10>5,'大','小');
SELECT last_name,commission_pct,IF(commission_pct IS NULL,'没奖金','有奖金') 备注 FROM employees;
(2)CASE函数的使用一
/*
CASE 要判断的字段或表达式
WHEN 常量1 THEN 要显示的值1或语句1
WHEN 常量2 THEN 要显示的值2或语句2
WHEN 常量3 THEN 要显示的值3或语句3
...
ELSE 值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;
(3)CASE函数的使用二
/*
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;
6.分组函数
(1)简单的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
(2)特点
①语法
select max(字段) from 表名;
②支持的类型
sum和avg一般用于处理数值型
max、min、count可以处理任何数据类型
③以上分组函数都忽略null
④都可以搭配distinct使用,实现去重的统计
select sum(distinct 字段) from 表;
⑤count函数
count(字段):统计该字段非空值的个数
count(*):统计结果集的行数
⑥ 和分组函数一同查询的字段,要求是group by后出现的字段
六、分组查询
1.简单的分组查询
#案例一:每个工种的最高工资
SELECT job_id, MAX(salary) FROM employees GROUP BY job_id;
#案例二:查询每个位置上的部门个数
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
2.添加筛选条件
#案例一:查询邮箱中包含a字符的每个部门的平均工资
SELECT department_id,AVG(salary) FROM employees WHERE email LIKE ('%a%') GROUP BY department_id;
#案例二:查询有奖金的每个领导手下员工的最高工资
SELECT manager_id,MAX(salary) FROM employees WHERE commission_pct IS NOT NULL GROUP BY manager_id;
3.添加复杂的筛选条件
#案例一:查询哪个部门的员工个数大于2
SELECT department_id,COUNT(*) FROM employees GROUP BY department_id HAVING COUNT(*)>2;
#案例二:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT job_id,MAX(salary) FROM employees WHERE commission_pct IS NOT NULL GROUP BY job_id HAVING MAX(salary)>12000;
#案例三:查询领导编号大于102的每个领导手下的最低工资大于5000的领导编号是哪个,以及其最低工资
SELECT manager_id,MIN(salary) FROM employees WHERE manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000;
4.按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数大于5的有哪些
SELECT COUNT(*),LENGTH(last_name) AS 姓名长度 FROM employees GROUP BY 姓名长度 HAVING COUNT(*)>5;
5.按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资SELECT AVG(salary),department_id,job_id FROM employees GROUP BY department_id,job_id;
6.添加排序
#案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低排序
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id
ORDER BY AVG(salary) DESC;
七、连接查询
这里直接使用SQL99语法
1.内连接
(1)等值连接
#案例一:查询员工名、部门名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id;
#案例二:查询名字中包含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的城市名和部门个数(分组加筛选)
SELECT city,COUNT(*)
FROM departments d INNER JOIN locations l
ON d.location_id=l.location_id
GROUP BY city
HAVING COUNT(*)>3;
#案例四:查询哪个部门的部门员工个数大于3的部门名和员工个数,并按个数降序(排序)
SELECT department_name,COUNT(*)
FROM departments d
INNER JOIN employees e
ON d.department_id=e.department_id
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;
#案例五:查询员工名、部门名、工种名、并按部门名降序(添加三表连接)
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 department_name DESC;
(2)非等值连接
#案例一:查询员工的工资级别
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades jg
ON e.salary BETWEEN jg.lowest_sal AND jg.highest_sal;
#案例二:查询工资级别的个数大于20的个数,并按工资级别降序
SELECT salary,grade_level,COUNT(*)
FROM employees e
INNER JOIN job_grades jg
ON e.salary BETWEEN jg.lowest_sal AND jg.highest_sal
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY grade_level DESC;
(3) 自连接
#案例一:查询员工的名字、上级的名字
SELECT e.last_name 员工名,m.last_name 领导名
FROM employees e
INNER JOIN employees m
ON e.manager_id=m.employee_id;
#案例二:查询姓名中包含字符k的员工的名字、上级的名字
SELECT e.last_name 员工名,m.last_name 领导名
FROM employees e
INNER JOIN employees m
ON e.manager_id=m.employee_id
where e.last_name LIKE ('%k%');
2.外连接
#引入:查询没有男朋友的女神名
(1) 左外连接
SELECT b.name,bo.*
FROM beauty b
LEFT JOIN boys bo
ON b.boyfriend_id=bo.id
WHERE bo.id IS NULL;
(2) 右外连接
SELECT b.name,bo.*
FROM boys bo
RIGHT JOIN beauty b
ON b.boyfriend_id=bo.id
WHERE bo.id IS NULL;
#案例一:查询哪个部门没有员工
#左外连接
SELECT d.*,e.employee_id
FROM departments d
LEFT JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id IS NULL;
#右外连接
SELECT d.*,e.employee_id
FROM employees e
RIGHT JOIN departments d
ON d.department_id=e.department_id
WHERE e.employee_id IS NULL;
(3) 全外连接
(4) 交叉连接
八、子查询
1.WHERE或having后面
(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 和工资
#①查询141号员工的job_id
SELECT job_id
FROM employees
WHERE employee_id='141';
#②查询143员工的salary
SELECT salary
FROM employees
WHERE employee_id='143';
#③查询员工的姓名、job_id 、和工资,要求job_id=①并且salary>②
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'
);
#案例三:查询公司工资最少的员工的last_name,job_id和salary
#①查询公司的最低工资
SELECT MIN(salary)
FROM employees;#②查询公司工资最少的员工的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)
FROM employees e
WHERE department_id='50';#②查询每个部门的最低工资
SELECT MIN(salary)
FROM employees
GROUP BY department_id;#③查询最低工资大于①结果的部门id和最低工资
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id='50'
);
#非法使用标量子查询
(2)列子查询(多行子查询)
#案例一:查询location_id是1400或1700的部门中的所有员工姓名
#①查询location_id是1400或1700的部门
SELECT department_id
FROM departments
WHERE location_id IN('1400','1700');#②查询①结果中的所有员工的姓名
SELECT last_name
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id IN('1400','1700')
);
#案例二:查询其他部门中比job_id为‘IT_PROG’部门任一工资低的员工的:工号、姓名、job_id和salary
#①查询job_id为‘IT_PROG’部门的工资
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG';#②查询员工的工号、姓名、job_id和salary,salary<①结果的任意一个
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<>'IT_PROG';#或
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
SELECT DISTINCT ,MAX(salary)
FROM employees
WHERE job_id='IT_PROG'
) AND job_id<>'IT_PROG';
#案例三:查询其他部门中比job_id为‘IT_PROG’部门所有工资低的员工的:工号、姓名、job_id和salary
#①查询job_id为‘IT_PROG’部门的工资
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG';#②查询员工的:工号、姓名、job_id和salary ,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<>'IT_PROG';#或
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
SELECT DISTINCT MIN(salary)
FROM employees
WHERE job_id='IT_PROG'
) AND job_id<>'IT_PROG';
(3)行子查询(一行多列或多列多行)
#案例:查询员工编号最小并且工资最高的员工信息#常规方法
#①查询最小的员工编号
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
);
2.select 后面
#案例:查询每个部门的员工个数
#之前的方法
SELECT COUNT(*),d.department_id
FROM departments d
JOIN employees e
ON d.department_id=e.department_id
GROUP BY e.department_id;
#子查询方法
SELECT d.*,(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id=d.department_id
)个数
FROM departments d;
#案例二:查询员工号=102的部门名
SELECT (
SELECT department_name
FROM departments d
INNER JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id=102
) 部门名;
3.from 后面
#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
select AVG(salary),department_id
FROM employees
GROUP BY department_id;#②查询每个部门的平均工资的工资等级
SELECT ag_dep.*,grade_level
FROM job_grades jg
INNER JOIN (select AVG(salary) ag,department_id
FROM employees
GROUP BY department_id) ag_dep
ON ag_dep.ag BETWEEN jg.lowest_sal AND jg.highest_sal;
4.exists 后面的子查询(相关子查询)
#案例一:查询有员工的部门名#EXISTS方法
SELECT department_name
FROM departments d
WHERE EXISTS (SELECT *
FROM employees e
WHERE d.department_id=e.department_id
);
#IN 方法select department_name
FROM departments d
WHERE d.department_id IN(
SELECT department_id
FROM employees e
);
#案例二:查询没有女朋友的男神信息
#EXISTS
SELECT *
FROM boys bo
WHERE NOT EXISTS(
SELECT boyfriend_id
FROM beauty b
WHERE bo.id=b.boyfriend_id
);#IN
SELECT bo.*
FROM boys bo
WHERE bo.id NOT IN(
SELECT boyfriend_id
FROM beauty);
九、分页查询
1.语法
select 查询列表
from 表
limit 【offset,】size;
注意:
offset代表的是起始的条目索引,默认从0开始
size代表的是显示的条目数
2.特点
①limit语句放在查询语句的最后
②公式:
假如要显示的页数为page,每一页条目数为size
select 查询列表
from 表
limit (page-1)*size,size;
#案例一:查询前五条员工信息
SELECT * FROM employees
LIMIT 0,5;/
SELECT * FROM employees
LIMIT 5;
#案例二:查询第11条到第25条
SELECT * FROM employees
LIMIT 10,15;
#案例三:有奖金的员工信息,并且工资较高的前十名
SELECT * FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 0,10;
十、联合查询
#引入:查询部门编号>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;