DQL查询:
一、基础查询
1、查询字段:
SHOW DATABASES;
#基础查询
/*
语法:
select 查询列表 from 表名;
特点:
查询列表可以是表中的字段,常量值、表达式、函数
查询结果是一个虚拟的表格
*/
#先启用指定的库:
USE myemployees;
#1.查询表中单个字段
SELECT last_name FROM employees;
#2.查询表中的多个字段
#为了防止字段和关键字重名,可以加上着重号:``
SELECT `last_name`,`salary`,`email` FROM employees;
#3、查询表中的所有字段
# 如果用*,那么查询顺序和表中一样。
SELECT * FROM employees;
#运行:先选中,然后F9即可
查询结果:(后文略)
2、查询常量、表达式、函数
#4.查询常量值
SELECT 100;
#sql中不区分字符和字符串,都用单引号即可。
SELECT 'john';
#5.查询表达式
SELECT 100%98;
#6.查询函数
SELECT VERSION();
3、起别名
#7.起别名
#方式一:便于理解,如果要查询的字段有重名的情况,使用别名可以区分开。
SELECT 100%98 AS 结果;
SELECT last_name AS 姓 FROM employees;
#方式二:使用空格
SELECT last_name 姓 FROM employees;
#案例:查询salary,显示结果为 out put 这里Out put中间有特殊符号空格,所以建议加上双引号
SELECT salary AS "out put" FROM employees;
3、去重
去掉重复字段:
#8.去重
#案例:查询员工表中涉及到的所有部门编号
SELECT DISTINCT department_id FROM employees;
4、加号的作用与字符串拼接函数:concat();
#+号的作用
-- java中的+号
-- 1、运算符,两个操作数都为数值型
-- 2、连接符,只要有一个操作数为字符串
--
-- MySQL中,只有一个功能:运算符
-- select 100+90;这就是加法。
-- 两个操作数为数值型,做加法运算;
-- select '123' +90,有其中一方为字符型,试图将字符型数值转换成数值型
-- 如果转换成功,则继续做加法运算;
-- 如果转换失败,如select 'john' +90
-- 则将字符型数值转换成0,然后继续加。
-- 这里答案是90.
--
-- 如果其中一方为Null,不管另一方是什么,则结果肯定为Null.
如果要字符串拼接,使用concat函数。如下:
CONCAT('a','b','c') AS 结果;
#案例:查询员工名和姓,连接成一个字段,并显示为 姓名
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
二、条件查询
总体框架:
进阶2:条件查询
语法:
SELECT 查询列表 FROM 表名 WHERE 筛选条件;
分类:
1、按条件表达式筛选
条件运算符:> < = <> >= <=
2、按逻辑表达式筛选
逻辑运算符: && || !
AND OR NOT
3、模糊查询
LIKE
BETWEEN AND
IN
IS NULL
-- 一 按条件表达式筛选
-- 查询工资大于12000的员工信息
SELECT * FROM employees WHERE salary>12000;
-- 案例2:查询部门编号不等于90号的员工名和部门编号
SELECT
last_name,department_id
FROM
employees
WHERE
department_id <> 90;
按逻辑表达式筛选
查询工资在10000到20000之间的员工名、工资以及奖金
SELECT
last_name,salary,commission_pct
FROM
employees
WHERE
salary>=10000 AND salary<=20000;
案例2 查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT
*
FROM
employees
WHERE
NOT(department_id>=90 AND department_id<=110) OR salary>15000;
模糊查询:
三、模糊查询
LIKE
BETWEEN AND
IN
IS NULL
IS NOT NULL
1.like
案例 查询员工名中包含字符a的员工信息
SELECT
*
FROM
employees
WHERE
last_name LIKE '%a%';
百分号代表任意位置,a的前面可能有字符,也可能后面有字符
案例2 查询员工中第三个字符为e,第五个字符为a的员工名和工资
前面单个字符用下划线代替
SELECT
last_name,
salary
FROM
employees
WHERE
last_name LIKE '__e_a%';
案例3 查询员工名中第二个字符为_的员工名
SELECT
last_name
FROM
employees
WHERE
last_name LIKE '_\_%';
在需要的字符前面加上\即可转义。
2、 BETWEEN AND
查询员工编号在100到120之间的员工信息
SELECT
*
FROM
employees
WHERE
employee_id BETWEEN 100 AND 120;
可以提高语句简洁度
两个临界值需要升序。
3、in关键字
查询员工的工种编号是 IT_PROG、AD_VP AD_PRES中的一个员工名和工种编号
SELECT
last_name,
job_id
FROM
employees
WHERE
job_id = 'IT_PROT' OR job_id = 'AD_VP' OR job_id = 'AD_PRES';
SELECT
last_name,
job_id
FROM
employees
WHERE
job_id IN ('IT_PROT','AD_VP','AD_PRES');
特点:1.提高语句简洁度
2.in列表的值必须一致或兼容
3.不支持模糊搜索,不能用%或者_
4.is NULL
案例:查询没有奖金的员工名和奖金率
SELECT
last_name,
commission_pct
FROM
employees
WHERE
commission_pct IS NULL;
有的话,就是 IS NOT NULL;
=或<>不能用于判断null值
三、排序查询
排序查询
语法:
SELECT 查询列表
FROM 表
【where 筛选条件】
ORDER BY 排序列表 ASC|DESC
案例 查询员工信息,要求工资从高到低排序
SELECT
*
FROM
employees
ORDER BY
salary DESC;
默认升序
案例2 查询部门编号大于等于90的员工信息,按入职时间的先后进行排序
SELECT
*
FROM
employees
WHERE
department_id >=90
ORDER BY
hiredate ASC;
案例3 按表达式排序 按年薪的高低显示员工信息和年薪
SELECT
*,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY
salary*12*(1+IFNULL(commission_pct,0)) DESC;
案例4 按年薪的高低显示员工的信息和年薪 【按别名排序】
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY
年薪;
案例5:按姓名的长度显示员工的姓名和工资【按函数排序】
SELECT LENGTH(last_name) AS 字节长度,last_name,salary
FROM employees
ORDER BY 字节长度 DESC;
案例6:查询员工信息,要求先按工资排序,再按员工编号排序【按多个字段排序】
SELECT
*
FROM
employees
ORDER BY
salary ASC,employee_id ASC;
ORDER BY 字句可以支持单个字段,多个字段,表达式,函数,别名
ORDER BY 字句一般放在查询语句的最后面,limit字句除外
案例:查询员工的姓名和部门号和年薪,按年薪降序,按姓名升序
SELECT
last_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY
年薪 DESC,last_name ASC;
四、常见函数
一、单行函数
1、字符函数
concat拼接
substr截取子串
upper转换成大写
lower转换成小写
trim去前后指定的空格和字符
ltrim去左边空格
rtrim去右边空格
replace替换
lpad左填充
rpad右填充
instr返回子串第一次出现的索引
length 获取字节个数
2、数学函数
round 四舍五入
rand 随机数
floor向下取整
ceil向上取整
mod取余
truncate截断
3、日期函数
now当前系统日期+时间
curdate当前系统日期
curtime当前系统时间
str_to_date 将字符转换成日期
date_format将日期转换成字符
4、流程控制函数
if 处理双分支
case语句 处理多分支
情况1:处理等值判断
SELECT salary AS 原始工资,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;
情况2:处理条件判断
5、其他函数
version版本
database当前库
user当前连接用户
五、分组函数
sum 求和
max 最大值
min 最小值
avg 平均值
count 计数
特点:
1、以上五个分组函数都忽略null值,除了count(*)
2、sum和avg一般用于处理数值型 max、min、count可以处理任何数据类型
3、都可以搭配distinct使用,用于统计去重后的结果
4、count的参数可以支持:
字段、*、常量值,一般放1
建议使用 count(*)
练习:
1.查询公司员工工资的最大值,最小值,平均值,总和
SELECT
MAX(salary) mx_sal,
MIN(salary) xi_sal,
ROUND(AVG(salary),2) ag_sal,
SUM(salary) sm_sal
FROM
employees;
round保留2位小数
2.查询员工表中的最大入职时间和最小入职时间的相差天数
SELECT DATEDIFF(MAX(hiredate),MIN(hiredate));
3.查询部门编号为90的员工个数
SELECT COUNT(*) 个数
FROM employees
WHERE department_id = 90;
六、分组查询
1.查询每个工种的最高工资
SELECT
MAX(salary),job_id
FROM
employees
GROUP BY
job_id;
2.查询每个位置上的部门个数
SELECT COUNT(*),location_id
FROM
departments
GROUP BY
location_id;
添加筛选条件
1.查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
案例2:查询有奖金的每个领导手下员工的最高工资
SELECT
MAX(salary),manager_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
manager_id;
添加复杂筛选条件
1.查询哪个部门的员工个数>2
1 查询每个部门的员工个数
2 筛选出大于2的部门
having用于分组后的筛选
SELECT
department_id,COUNT(*)
FROM
employees
GROUP BY
department_id
HAVING COUNT(*)>2;
案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
1 查询每个工种有奖金的员工的最高工资
SELECT
MAX(salary),job_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
job_id;
2 根据1的结果继续筛选,最高工资>12000
SELECT
MAX(salary),job_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
job_id
HAVING
MAX(salary)>12000;
案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号
以及其最低工资
SELECT
MIN(salary),manager_id
FROM
employees
WHERE
manager_id >102
GROUP BY
manager_id
HAVING
MIN(salary)>5000;
分组查询的筛选条件分为两类
数据源不一样
分组前筛选:原始表 使用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
job_id,department_id
ORDER BY AVG(salary) DESC;
GROUP BY 子句支持单个字段分组,多个字段分组,
多个字段用逗号隔开没有顺序要求,表达式或函数(用的较少)
也可以添加排序(放在最后)
练习:
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.查询员工最高工资和最低工资的差距
SELECT MAX(salary)-MIN(salary) difference
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 department_id,COUNT(*),AVG(salary)
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) DESC;
5.选择具有各个job_id的员工人数
SELECT COUNT(*),job_id
FROM employees
WHERE job_id IS NOT NULL
GROUP BY job_Id;
七、连接查询
含义:又称多表查询
笛卡尔乘积现象
表1有m行,表2有n行
结果有m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id = boys.id;
记得加作用域!
分类:
按年代分类:SQL 92仅仅支持内连接
SQL 99 支持内连接+外连接(左右)+交叉连接按功能分类:
内连接:
等值连接
非等值连接
自连接外连接:
左外连接
右外连接
全外连接交叉连接
1、等值连接
1.等值连接
案例1 查询女神名和对应男神名
SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id = boys.id;
USE myemployees;
#案例2 查询员工名和对应的部门名
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,jobs
WHERE employees.`job_id` = jobs.`job_id`;
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;
案例2 查询城市名中第二个字符为o的部门名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.location_id = l.location_id
AND l.city LIKE '_o%';
是否能加分组?
案例1:查询每个城市的部门个数
SELECT COUNT(*),city
FROM departments d,locations l
GROUP BY city;
案例2 查询有奖金的每个部门的部门名和部门的领导编号,和该部门的最低工资
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;
三表连接:
案例 查询员工名,部门名和所在城市
SELECT
e.last_name,d.department_name,l.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 g
WHERE salary BETWEEN g.lowest_Sal AND g.highest_sal;
3.自连接
案例:查询员工名和上级的名称
七*、SQL99语法 的内外链接
语法:
SELECT 查询列表
FROM 表1 别名[连接类型]
JOIN 表1 别名[连接类型]
ON 连接条件
【where 筛选条件】
【group BY 分组】
【having 筛选条件】
【order BY 排序列表】分类:
内连接:inner
左外连接:left OUTER
右外连接:right OUTER
全外连接:full OUTER
交叉连接:cross
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 COUNT(*),city,department_id
FROM departments d
INNER JOIN locations l
ON d.location_id = l.location_id
GROUP BY city
HAVING COUNT(*) > 3;
案例4 查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序
SELECT e.department_id,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;
案例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 DESC;
2.非等值连接
查询员工工资级别
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal;
查询工资级别>2的个数,并且按工资级别降序
SELECT COUNT(*),salary,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;
3.自连接
自连接
查询员工名字,上级的名字
SELECT e.last_name,m.last_name
FROM employees e
INNER JOIN employees m
ON e.manager_id = m.employee_id;
外连接
外连接用于查询一个表中有,一个表中没有的情况。
有主表和从表
外连接的查询记录为主表中的所有记录
从表中有匹配的,就匹配
无匹配的,就成为NULL
外连接结果 = 内连接结果+主表中有而从表中没有的记录。
左外连接:主表left join从表
右外连接:从表right join主表
左外和右外交换顺序可实现同样效果。
外连接
引入 查询男朋友不在男神表的女神名
USE girls;
外连接用于查询一个表中有,一个表中没有的情况
引入 查询男朋友不在男神表的女神名
SELECT b.name,boys.*
FROM beauty b
LEFT OUTER JOIN boys
ON b.boyfriend_id = boys.id;
USE myemployees;
案例1 查询哪个部门没有员工
左外
SELECT d.department_name,employee_id
FROM departments d
LEFT OUTER JOIN employees e
ON d.department_id = e.department_id
WHERE e.employee_id IS NULL;
右外
SELECT d.department_name,employee_id
FROM employees e
RIGHT OUTER JOIN departments d
ON d.department_id = e.department_id
WHERE e.employee_id IS NULL;
4.全外连接
5.交叉连接
也就是笛卡尔乘积。
八、子查询
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询
示例:
分类:
按子查询出现的位置:
select后面
仅仅支持标量子查询
from后面
表子查询
where或者having后面【重要】
标量子查询,
列子查询,
行子查询
exists后面(相关子查询)
表子查询
按结果集的行列数不同
标量子查询:结果集只有一行一列
行子查询:结果集有一行多列
列子查询:结果集只有一列多行
表子查询:结果集一般为多行多列
1.标量子查询
一.where或者having后
1.标量子查询
特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配着单行操作符使用
4.列子查询,一般搭配着多行操作符使用
标量子查询
案例一:谁的工资比阿贝尔高?
1.查询阿贝尔的工资
USE myemployees;
SELECT salary
FROM employees
WHERE last_name = 'Abel';
SELECT last_name
FROM employees
WHERE salary>(SELECT salary
FROM employees
WHERE last_name = 'Abel');
案例2 返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
SELECT job_id
FROM employees
WHERE employee_id = 141;
SELECT salary
FROM employees
WHERE employee_id = 143;
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:返回公司工资最少的员工的信息
SELECT last_name,job_id,salary
FROM employees
WHERE salary =(SELECT MIN(salary)
FROM employees) ;
2.列子查询(多行子查询)
一列多行
案例1:返回location_id是1400或1700的部门中所有员工姓名
1.先查location_id是1400或1700的部门编号
SELECT department_id
FROM departments
WHERE location_id = 1400 OR location_id = 1700;
2.再查询姓名,要求部门号是1中某一个
SELECT last_name
FROM employees
WHERE department_id IN
(SELECT department_id
FROM departments
WHERE location_id = 1400 OR location_id = 1700);
3.返回其他部门中比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<>'IT_PORG';
4.返回其他部门中比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<>'IT_PORG';
3.放在select后的子查询
4.放在exists后的子查询
看子查询后有无值
(in的方式)
(exists的方式)
九、分页查询
应用场景:
实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句
语法:
select 字段|表达式,...
from 表
【where 条件】
【group by 分组字段】
【having 条件】
【order by 排序的字段】
limit 【起始的条目索引,】条目数;
特点:
1.起始条目索引从0开始
2.limit子句放在查询语句的最后
3.公式:select * from 表 limit (page-1)*sizePerPage,sizePerPage
假如:
每页显示条目数sizePerPage
要显示的页数 page
案例1 查询前五条员工信息
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;
特点:
1.limit语句放在查询语句最后
2.公式:
要显示的页数是page
每页条目数是size
SELECT 查询列表 FROM 表
LIMIT (page-1)*size,size;
十、union联合查询
引入:
union 联合、合并
语法:
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
.....
select 字段|常量|表达式|函数 【from 表】 【where 条件】
特点:
1、多条查询语句的查询的列数必须是一致的
2、多条查询语句的查询的列的类型几乎相同
3、union代表去重,union all代表不去重
联合查询
UNION 联合,合并 将多条查询语句的结果合并成一个结果
引入的案例:查询部门编号大于90或者邮箱中包含a的员工信息
SELECT *
FROM employees
WHERE email LIKE '%a%'
UNION
SELECT *
FROM employees
WHERE department_id>90;
应用场景
查询中国用户中男性的信息以及外国用户中男性的信息
SELECT id,cname,csex
FROM t_ca
WHERE csex = '男'
UNION
SELECT t_id,tName,tGender
FROM t_ua
WHERE tGender = 'male';