MySQL基础学习篇(2)——DQL

MySql基础学习

注明:文章笔记均来自哔哩哔哩视频学习

七、数据查询【重点】

7.1 数据库表的基本结构

关系数据库是以表格(Table)进行数据存储,表格由“行”和“列”组成

  • 经验:执行查询语句返回的结果是一张虚拟表

7.2 基本查询

语法:SELECT列名FROM表名

关键字描述
SELECT指定要查询的列
FROM指定要查询的表
7.2.1 查询部分列
# 查询员工表中所有员工的编号】你名字、邮箱
select employee_id fist_name, email
from t_employee
7.2.2查询所有列
# 查询所有列
# 1、使用*的方式
SELECT * FROM t_employees;
# 2、使用列名的方式
SELECT 所有列的列名 FROM t_employees;
  • 注意:生产环境下,优先使用列名查询,*的方式需要转换成全列名。效率低,可读性差
7.2.3 对列中的数据进行运算
# 查询员工的编号、名字、年薪
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY * 12 FROM t_employees
算数运算符描述
+两列做加法运算
-两列做减法运算
*两列做乘法运算
/两列做除法运算
  • % 是占位符。而并非模运算符
7.2.4 列的别名

列 as 列名

SELECT EMPLOYEE_ID '编号',FIRST_NAME AS '姓氏',SALARY * 12 AS '年薪' FROM t_employees;
7.2.5 查询结果去重

distinct 列名

# 查询员工表中有多少个经理
SELECT DISTINCT MANAGER_ID FROM t_employees;

7.3 排序查询

语法:SELECT 列名 FROM 表名 ORDER BY排序列[排序规则]

排序规则描述
ASC对前面排序列做升序排列
desc对前面排序列做降序排序
7.3.1 依据单列排序
# 对员工工资进行升序排序
SELECT EMPLOYEE_ID,salary FROM t_employees ORDER BY salary + 0 ASC;
# 对员工工资进行降序排序
SELECT EMPLOYEE_ID,salary FROM t_employees ORDER BY salary + 0 DESC;

7.3.2 依据多列排序
# 按照工资高低进行降序排序,如果工资相等,按照员工编号升序进行排序
SELECT EMPLOYEE_ID,salary FROM t_employees ORDER BY salary + 0 DESC, EMPLOYEE_ID DESC;

7.4 条件查询

语法: SELECT 列名 FROM 表名 WHERE 条件

关键字描述
where 条件在查询结果中,筛选符合查询条件的查询结果,条件为布尔表达式
7.4.1 等值判断
# 查询符合条件的数据
SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY = 11000

SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY = 24000
  • 注意:与java不同(==),mysql中等值判断使用=
7.4.2 逻辑判断(and 、or、 not)
SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY = 11000 AND COMMISSION_PCT = 0.30 AND EMPLOYEE_ID = '148';

SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY = 11000 OR COMMISSION_PCT = 0.30;

SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE NOT SALARY = 11000;
7.4.3 不等值判断(>、 <、>=、<=、<>、!=)
SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY != 11000;

SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY <> 11000;

# 查询工资区间在[6000, 10000]之间
SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY >= 6000 AND salary <= 10000;
7.4.4 区间判断(between 起始and 终止)
# 查询工资区间在[6000, 10000]之间
SELECT EMPLOYEE_ID, FIRST_NAME,salary
FROM t_employees
WHERE SALARY BETWEEN 6000 AND 10000;
  • 注意:在区间判断中,小值在前,大值在后,反之,得不到结果
7.4.5 null值判断(is null、is not null)
# 查询出经理编号为null的员工信息
SELECT employee_id, FIRST_NAME,MANAGER_ID
FROM t_employees
WHERE MANAGER_ID IS NULL;

SELECT employee_id, FIRST_NAME,MANAGER_ID
FROM t_employees
WHERE MANAGER_ID IS NOT NULL;
7.4.6 枚举查询(IN(值1, 值2,值3))

# 查询部门编号为70,80,90 的员工信息
SELECT EMPLOYEE_ID, FIRST_NAME,SALARY,department_id
FROM t_employees
WHERE department_id = 70 OR department_id = 80 OR department_id = 90;

SELECT EMPLOYEE_ID, FIRST_NAME,SALARY,department_id
FROM t_employees
WHERE department_id IN (70,80,90);
# in 的效率在大数据面前较低
7.4.7 模糊查询
  • LIKE_(单个任由字符)

​ 列名 LIKE ‘张__’

  • LIKE %(任意长度的任意字符)

    列名 LIKE ‘张%’

  • 注意:模糊查询只能和LIKE关键字结合使用
# 查询L开头的三个字的员工信息
SELECT EMPLOYEE_ID, FIRST_NAME, SALARY
FROM t_employees
WHERE FIRST_NAME LIKE 'L__';
# 查询所有以L开头的员工信息
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY
FROM t_employees
WHERE first_name LIKE '张%';
7.4.8 分支结构查询
CASE
    WHEN 条件1 THEN 结果1
    WHEN 条件2 THEN 结果2
    WHEN 条件3 THEN 结果3
    ELSE 结果
END
  • 注意:通过使用case end进行条件判断,每条数据对应生成一个值
  • 经验:类似java中的switch
# 查询员工信息
SELECT EMPLOYEE_ID, FIRST_NAME, SALARY,department_id,
CASE
	WHEN SALARY >= 10000 THEN 'A'
	WHEN SALARY >= 8000 AND SALARY < 10000 THEN 'B'
	WHEN SALARY >= 6000 AND SALARY < 8000 THEN 'C'
	WHEN SALARY >= 4000 AND SALARY < 6000 THEN 'D'
	ELSE 'E'
END AS "level"
FROM t_employees;

7.5 时间查询

select 时间函数([参数列表])

  • 经验:执行时间函数查询,会自动生成一张虚表
时间函数描述
SYSDATE当前系统时间(日月年时分秒)
CURDATE获取当前日期
CURTIME获取当前时间
WEEK(DATE)获取指定日期为一年中的第几周
YEAR(DATE)获取指定日期的年份
HOUR(TIME)获取指定时间的小时值
MINUTE(TIME)获取时间的分钟值
DATEDIFF(DATE,DATE2)获取DATE1和DATE2之间相隔的天数
ADDDATE(DATE,N)计算DATE加上N天后的日期
# 当前系统的时间
SELECT SYSDATE();
# 当前系统的ri期
SELECT CURDATE();
# 获取系统时间
SELECT CURTIME();
# 获取指定日期为一年中的第几周
SELECT WEEK(SYSDATE());
# 获取指定日期忠厚的年份
SELECT YEAR(SYSDATE());
# 获取小时值
SELECT HOUR(CURTIME());
# 获取分钟值
SELECT MINUTE(CURTIME());
# 指定日期之间的相隔天数
SELECT DATEDIFF('2020-4-1','2019-4-1');
# 计算date日期加上n天后的日期
SELECT	ADDDATE('2020-4-1', 5);

7.6 字符串查询

语法: SELECT 字符串函数([参数列表])

字符串函数说明
concat(str1, …)将多个字符串拼接
insert(str, pos, len, newStr)将str中指定pos位置开始len长度的内容替换为newStr
lower(str)将指定字符串转换诶小写
upper(str)将指定字符串转换为大写
substring(str, num, len)将str字符串指定num位置开始截取len个内容

# 多个字符串拼接
SELECT CONCAT('My', 'S,', 'QAL');
SELECT CONCAT(FIRST_NAME,'-', last_name) FROM t_employees;
# 字符串替换
SELECT INSERT('这是一个数据库',3, 2, 'MySql')
# 字符串转小写
SELECT LOWER('LOWER')
# 字符串转大写
SELECT UPPER('shdiuashdui')
# 指定内容截取
SELECT SUBSTRING('JaavaMySqlStrSub',6,6);
# MySqlS

7.7 聚合函数

语法: SELECT 聚合函数(列名) FROM 表名;

  • 经验:对多条数据的单列进行统计,返回统计后的一行结果
聚合函数说明
SUM()求所有行中单列结果的总和
AVG()平均值
MAX()最大值
MIN()最小值
COUNT()求总行数
# 聚合函数
# 求单列所有数据的和
SELECT SUM(SALARY) FROM t_employees;
# 求单列所有数据的平均值
SELECT AVG(SALARY) FROM t_employees;
# 求单列最大值
SELECT MAX(SALARY + 0) FROM t_employees;
# 求单列最小值
SELECT MIN(salary + 0) FROM t_employees;
# 求总行数 员工总数
SELECT COUNT(EMPLOYEE_ID) FROM t_employees;
# 统计有提成的人数 会自动忽略null值,不进行统计
SELECT COUNT(COMMISSION_PCT) FROM t_employees;
  • 注意:聚合函数会自动忽略null值,不进行统计

7.8 分组查询

语法:SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组依据(列);

关键字说明
GROUP BY分组依据,必须在WHERE之后生效
# 查询各个部门的额总人数
SELECT department_id, COUNT(employee_id)
FROM t_employees
GROUP BY department_id;
# 查询各个部门的平局工资
SELECT department_id, AVG(salary)
FROM t_employees
GROUP BY department_id;
# 查询各个部门、各个岗位的总人数
SELECT department_id,job_id, COUNT(employee_id)
FROM t_employees
GROUP BY department_id, job_id;
# 常见问题:查询各个部门id,总人数、first_name
SELECT department_id,COUNT(employee_id), first_name
FROM t_employees
GROUP BY department_id;
  • 分组查询中,select显示的列只能是分组依据列,或者聚合函数列,不能出现其他列

7.9 分组过滤查询

语法:SELECT 列名 FROM 表名 WHERE 条件 GROUNP BY 分组列 HAVING 过滤规则

关键字说明
HAVING过滤规则过滤规则定义对分组后的数据进行过滤

统计部门的最高工资

#思路
#1.确定分组依据(DEPARTMENT_ID)
#2.对分组后的数据,过滤出部门编号是60、70、90信息
#3.MAX()函数
SELECT DEPARTMENT_ID,MAX(SALARY) 
FROM t_employees GROUP BY DEPARTMENT_ID 
HAVING DEPARTMENT_ID IN (60,70,90);
#GROUP确定分组依据DEPARTMENT_ID
#HAVING过滤出60,70,90的部门
#SELECT查看部门编号和MAX函数

7.10 限定查询

语法SELECT 列名 FROM 表名 LIMIT 起始行,查询行数

关键字说明
LIMIT offset_start,row_count限定查询结果的起始行和总行数
7.10.1 查询前5行记录
#查询表中前五名员工的所有信息
SELECT * FROM t_employees LIMIT 0,5;
  • 注意起始行是从0开始代表了第一行第二个参数代表的是从指定行开始查询几行
7.10.2 查询范围记录
#查询表中从第四行开始,查询10行
SELECT * FROM t_employees LIMIT 3,10;
7.10.3 LIMIT典型应用

分页查询:一页显示10条,一共查询三页。

#思路:第一页是从0开始,显示10条
SELECT * FROM t_employees LIMIT 0,10;
#第二页是从10条开始,显示10条
SELECT * FROM t_employees LIMIT 10,10;
#第三页是从20条开始,显示10条
SELECT * FROM t_employees LIMIT 20,10;
  • 在分页应用场景中,起始行是变化的,但是一页显示的页数是不变的

7.11 查询总结

7.11.1 SQL语句编写顺序

COPYSELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组 HAVING 过滤条件 ORDER BY 排序列(ASC|DESC) LIMIT 起始行,查询行数

7.11.2 SQL语句执行顺序
COPY1.FROM:指定数据来源表
2.WHERE:对查询数据第一次过滤
3.GROUP BY:分组
4.HAVING:对分组后的数据第二次过滤
5.SELECT:查询各字段的值
6.ORDER BY:排序
7.LIMIT:限定查询结果

7.12 子查询(作为条件判断)

语法SELECT 列名 FROM 表名 WHERE 条件(子查询结果)

7.12.1 查询工资大于Bruce的员工信息
#1.先查询到Bruce的工资(一行一列)
SELECT SALARY FROM t_employees WHERE FIRST_NAME = 'Bruce';
#2.查询工资大于Bruce的员工信息
SELECT * FROM t_employees WHERE SALARY > 6000;
#3.将前两句整合
SELECT * FROM t_employees 
WHERE SALARY > 
(SELECT SALARY FROM t_employees WHERE FIRST_NAME = 'Bruce');
  • 注意将子查询一行一列的结果作为外部查询的条件做第二次查询
  • 子查询得到一行一列的结果才能作为外部查询的等值判断条件或不等值判断条件

7.13 子查询(作为枚举查询的条件)

语法SELECT 列名 FROM 表名 WHERE 列名 IN (子查询结果);

7.13.1 查询与名为“KING”同一部门的员工信息
#思路
#1.先查询KING所在的部门编号
SELECT DEPARTMENT_ID FROM t_employees WHERE LAST_NAME = 'King';#80,90
#2.再查询80,90号部门的员工信息
SELECT * FROM t_employees WHERE DEPARTMENT_ID IN(80,90);
#3.SQL:合并
SELECT * FROM t_employees 
WHERE DEPARTMENT_ID IN
(SELECT DEPARTMENT_ID FROM t_employees WHERE LAST_NAME = 'King');
  • 将子查询多行一列的结果作为外部查询的枚举查询条件做第二次查询
7.13.2 工资高于60编号部门的员工信息
#1.查询60编号部门所有人的工资(多行单列)
SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = 60;
#2.查询工资高于60编号部门所有人的工资的员工信息(高于所有)
SELECT * FROM t_employees 
WHERE SALARY > 
ALL(SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = 60);
#3.查询工资高于60编号部门的员工信息(高于部分)
SELECT * FROM t_employees 
WHERE SALARY > 
ANY(SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = 60);
  • 注意当子查询结果集形式为多行单列时可以使用ANY或ALL关键字

  • ALL表示查询高于部门所有员工工资的员工信息;ANY表示查询只需要高于部门中任意一名员工工资的员工信息

7.14 子查询(作为一张表)

查询到一张多行多列的临时表,这张表也可以作为查询数据源。

语法SELECT 列名 FROM (子查询的结果集) WHERE 条件;

7.14.1 查询员工表中工资排名前5名的员工信息
#思路:
#1.先对所有员工的薪资进行排序(排序后的临时表)
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees ORDER BY SALARY DESC;
#2.再查询临时表中前5行员工信息
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM (临时表) LIMIT 0,5;
#3.合并
SELECT * FROM 
(SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees ORDER BY SALARY DESC) AS 临时表 LIMIT 0,5;
  • 将子查询多行多列的结果作为外部查询的一张表做第二次查询
  • 注意子查询作为临时表需要为其赋予一个临时表名

7.15 合并查询

  • SELECT * FROM 表名1 UNION SELECT * FROM 表名2
  • SELECT * FROM 表名1 UNION ALL SELECT * FROM 表名2
  • 返回的查询结果是将表1的结果和表2的结果做了一个合并。
15.1 合并两张表的结果(去除重复记录)
#合并两张表的结果,去除重复记录
SELECT * FROM T1 UNION SELECT * FROM T2;
  • 注意合并结果的两张表列数必须相同列的数据类型可以不同

列数必须相同是因为该合并做了一个纵向合并,两个4列多行的结果集表合并后也是一个4列多行的表,但是合并后的列名以第一个结果集表为准。

7.15.2 合并两张表的结果(保留重复记录)
#合并两张表的结果,不去除重复记录(显示所有)
SELECT * FROM T1 UNION ALL SELECT * FROM T2;

该合并结果会保留两张查询表中重复的记录,而UNION只保留第一个不重复的记录

7.16 表连接查询

语法:SELECT 列名 FROM 表1 连接方式 表2 ON 连接条件

7.16.1 内连接查询(INNER JOIN ON)
#1.查询所有员工的职员和职位信息 SQL标准
SELECT * FROM t_employees INNER JOIN t_jobs 
ON t_employees.JOB_ID = t_jobs.JOB_ID;
#2.查询所有员工的职员和职位信息 MYSQL
SELECT * FROM t_employees,t_jobs WHERE t_employees.JOB_ID = t_jobs.JOB_ID;

如果没有指定连接条件,则会造成笛卡尔积的结果,第一张表中的每行数据都会和第二张表进行连接。

  • 经验在MySQL中第二种方式也可以作为内连接查询但是不符合SQL标准
  • 而第一种属于SQL标准与其他关系型数据库通用
7.16.2 三表连接查询
#查询所有员工工号、名字、部门名称、部门所在国家ID
SELECT EMPLOYEE_ID,FIRST_NAME,t_departments.DEPARTMENT_NAME,t_locations.COUNTRY_ID 
FROM t_employees
INNER JOIN t_departments ON	
t_employees.DEPARTMENT_ID=t_departments.DEPARTMENT_ID
INNER JOIN t_locations ON	
t_departments.LOCATION_ID=t_locations.LOCATION_ID;

该语句查询出来的结果没有员工编号为178的员工信息,该名员工的部门ID为NULL,不符合连接条件,所以不包含在匹配出的结果集中,你可以自己动手尝试并查看结果。之所以提这个是因为可以与下节的语句区分开来。

7.16.3 左外连接(LEFT JOIN ON)
#查询所有员工的工号、名字、工资及其对应的部门名称(没有部门的员工也在查询结果中,部门名称以NULL值补充)
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY,DEPARTMENT_NAME 
FROM t_employees
LEFT JOIN t_departments 
ON t_departments.DEPARTMENT_ID=t_employees.DEPARTMENT_ID;

该语句查询出来的结果包含没有部门的178号员工,DEPARTMENT_NAME的值被填充为NULL。

  • 注意左外连接是以左表作为主表依次向右匹配匹配到则返回结果
  • 匹配不到则返回NULL值填充
7.16.4 右外连接(RIGHT JOIN ON)
#查询所有部门信息,以及此部门中的所有员工信息(没有员工的部门也在查询结果中,员工信息以NULL值填充)
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY,DEPARTMENT_NAME 
FROM t_employees
RIGHT JOIN t_departments 
ON t_departments.DEPARTMENT_ID=t_employees.DEPARTMENT_ID;

该查询结果以部门表作为主表,有些部门没有员工,其员工信息全部为NULL。

  • 注意右外连接是以右表为主表依次向左匹配匹配到返回结果
  • 匹配不到则返回NULL值填充
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值