目录
- 数据准备
- DQL语言的学习
- 基础查询
- 条件查询
- 排序查询
- 分组查询
- 常见函数
- 连接查询
- 子查询
- 分页查询
- union联合查询
前言
当你读到这篇文章时,前提是已经将MySQL的环境以及客户端安装完成(如未安装可参考上篇文章),并掌握了它的基础知识。那么,今天我们来学习SQL语言的DQL,SQL语言分别包括DQL数据查询、DML数据操作、DDL数据定义、TCL事务控制。工作中最常用的是数据查询和数据操作语言;数据定义(建库、建表等)一般由拥有权限的开发人员或者管理人员来创建;事务控制语言通常在开发场景使用的更多。所以,如果你是偏业务或者数据分析方向,重点学习前两个就够用。
数据准备
接下来,我们将使用员工相关的四张样本数据表,来学习SQL,建议你在学习过程中多动手练习,理解才会更深刻。表和字段含义,如下图:
如何利用SQL语句来操作以上数据呢?我们必须将样本数据导入MySQL客户端(如:Navicat)中。可以在客户端操作数据,或者在终端窗口。工作中经常在客户端操作,所以本文所有SQL语句将在Navicat中学习。
首先将sql脚本保存到桌面(获取方式:关注”Python之每日一课”公众号,后来回复”sql基础数据”,即可。),导入SQL脚本的具体操作流程如下:
1、 选中本地数据库—>点击运行SQL文件
2、 选中三个点—>选择要执行的SQL脚本—>打开
3、 点击开始—>数据导入成功—>关闭
4、选中库—>右键刷新—>完成!
现在数据准备完成。这里是导入sql脚本;导出同理,选择”转储SQL“文件。当然了,Navicat也支持将当前表或查询结果导出Excel、CSV等文件类型。
下面可以写SQL语句了(每个sql脚本可以保存,下次直接使用),如下:
DQL语言的学习
1、 基础查询
1)语法
<span>select</span> 要查询的东西 【<span>from</span> 表名】
2)特点
类似于Python中 :print(要打印的东西)
①通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
② 要查询的东西 可以是常量值、表达式、字段、也可以是函数
3)举栗
<span># 查询常量</span><span>SELECT</span> <span>100</span>;<span># 查询表达式</span><span>SELECT</span> <span>100</span> * <span>2</span><span># 查询单个字段</span><span>SELECT</span> last_name <span>FROM</span> employees;<span># 查询多个字段</span><span>SELECT</span> last_name,em<strong>ai</strong>l <span>FROM</span> employees;<span># 查询所有字段</span><span>SELECT</span> * <span>FROM</span> employees;<span># 查询表的记录总数(函数)</span><span>SELECT</span> <span>COUNT</span>(*) <span>FROM</span> employees;<span># 查询员工表中的部门编号并去重(字段前加关键字)</span><span>SELECT</span> <span>DISTINCT</span> department_id <span>FROM</span> employees;
补充:可以给字段起别名,好处是提高可读性,更方便理解;多表连接时,区分字段。用AS 或 空格来实现。如下:
2、 条件查询
条件查询:根据条件过滤原始表的数据,查询到想要的数据
1)语法
<span>select</span> 要查询的字段|表达式|常量值|函数<span>from</span> 表<span>where</span> 条件;
2)分类
①条件表达式
示例:salary><span>10000</span>条件运算符:> <span><span></span>= <span><<span>=</span> = <span>!</span>= </span></span>
②逻辑表达式
示例:salary><span>10000</span> && salary<<span>20000</span>逻辑运算符: <span>and</span>(&&)<span>:</span>两个条件如果同时成立,结果为<span>true</span>,否则为<span>false</span> <span>or</span>(<span>||</span>):两个条件只要有一个成立,结果为<span>true</span>,否则为<span>false</span> <span>not</span>(!):如果条件成立,则<span>not</span>后为<span>false</span>,否则为<span>true</span>
③模糊查询
<span># 常用关键字</span>likebetween <span>and</span><span>in</span>|exists<span>is</span>|<span>is</span> <span>not</span> <span>null</span>
3)举栗
<span># 查询工资大于12000的员工信息</span><span>SELECT</span> * <span>FROM</span> employees <span>where</span> salary ><span>12000</span>;<span># 查询工资大于10000同时小于2000的员工信息</span><span>SELECT</span> * <span>FROM</span> employees <span>WHERE</span> salary><span>10000</span> <span>AND</span> salary<<span>20000</span>;<span># 查询员工名中以字符a开头的员工信息 </span><span># %代表任意多个字符,如果需求为包含a的员工信息 就写为 %a%</span><span>SELECT</span> * <span>FROM</span> employees <span>WHERE</span> last_name <span>LIKE</span> <span>\'a%\'</span>;<span># 查询员工编号在100到120之间的员工信息(between and)</span><span># 写法一 逻辑表达式 and</span><span>SELECT</span> *<span>FROM</span> employees<span>WHERE</span> employee_id >= <span>100</span><span>AND</span> employee_id <= <span>120</span>;<span># 写法二 between and</span><span># 特点:1、简洁 2、包含临界值</span><span>SELECT</span> *<span>FROM</span> employees<span>WHERE</span> employee_id <span>BETWEEN</span> <span>100</span><span>AND</span> <span>120</span>;
⭐ 注意:where 一定要放到 from 后面。NULL 不是假,也不是真,而是”空”;任何运算符,判断符碰到NULL,都得NULL;NULL的判断只能用is null,is not null;NULL 影响查询速度,一般避免使值为NULL。exists查询可以与in型子查询互换,它们之间区别以后语句优化时会详细讲解。
3、 排序查询
1)语法
<span>select</span> 要查询的东西<span>from</span> 表名<span>where</span> 条件<span>order</span> <span>by</span> 排序的字段|表达式|函数|别名 【<span>asc</span>|<span>desc</span>】
2)举栗
<span># 查询员工信息,要求工资从高到低排序</span><span>SELECT</span> *<span>FROM</span> employees<span>ORDER</span> <span>BY</span> salary <span>DESC</span>;
⭐注意:order by 一定要放到 语句最后(limit前面)
4、分组查询
1)语法
<span>select</span> 分组函数(字段),字段[要求出现在<span>group</span> <span>by</span>后面的字段] <span>from</span> 表名<span>group</span> <span>by</span> 分组的字段
2)特点
①可以按单个字段分组
②和分组函数一同查询的字段最好是分组后的字段
③分组筛选(where 和 having区别)
⭐关键字 | ⭐针对的表 | ⭐位置 | ⭐执行顺序 |
where | 原始表 | group by前面 | 分组前筛选 |
having | 分组后结果集 | group by后面 | 分组后筛选 |
④可以按多个字段分组,字段之间用逗号隔开
⑤可以支持排序
⑥having后可以支持别名
3)举栗
<span># 简单分组:查询每个部门的平均薪资</span><span>SELECT</span> <span>AVG</span>(salary), department_id<span>FROM</span> employees<span>GROUP</span> <span>BY</span> department_id;<span># 添加筛选条件:查询2000(包含2000)年以前入职的各部门平均工资</span><span>SELECT</span> department_id, <span>AVG</span>(salary)<span>FROM</span> employees<span>WHERE</span> hiredate <= <span>\'2000-01-01\'</span><span>GROUP</span> <span>BY</span> department_id;<span># 添加复杂筛选条件:查询哪个部门的员工个数大于5,并按降序排列,取前两个</span><span># 思路1、先按部门分组,查询每个部门的员工个数 2、根据1、的结果进行筛选</span><span>SELECT</span> department_id, <span>COUNT</span>(*) <span>as</span> <span>num</span><span>FROM</span> employees<span>GROUP</span> <span>BY</span> department_id<span>HAVING</span> <span>num</span> >=<span>5</span><span>ORDER</span> <span>BY</span> <span>num</span> <span>DESC</span> <span>LIMIT</span> <span>2</span>;
⭐ 注意:关键字顺序是where —>group by—>having—>order by—>limit
(having不能单独使用,需结合group by ,表示对分组后的结果进行筛选;
而group by 必须结合分组聚合函数一起使用,比如:count()、max()等)
5、 常见函数
1)单行函数
2)分组函数
<span>sum</span>() 求和<span>max</span>() 最大值<span>min</span>() 最小值<span>avg</span>() 平均值<span>count</span>() 计数
3)分组函数特点
①以上五个分组函数都忽略null值,除了count(*)
②sum和avg一般处理数值型,max、min、count可以处理任何数据类型
③都可以搭配distinct使用,用于统计去重后的结果
④count的参数可以支持:字段、*、常量值,一般放1
6、连接查询(多表查询)
单个表不能满足需求时,需要结合多张表,去除有关联的数据。这时就需要用连接查询,连接查询有三种,通常join使用的最多。
1)连接方式一 :等值连接(连接条件有等号)——非等值连接(相反)
①等值连接的结果 = 多个表的交集
②多个表不分主次,没有顺序要求
③一般为表起别名,提高阅读性和性能
<span># 等值连接:查询所有员工的姓名、工种ID、工种名称</span><span>SELECT</span> a.last_name,a.job_id,b.job_title<span>FROM</span> employees a ,jobs b<span>WHERE</span> a.job_id = b.job_id;
2)连接方式二:通过join关键字实现连接
①语法
<span>select</span> 字段名,……<span>from</span> 表<span>1</span>【<span>inner</span>|<span>left</span>|<span>right</span>】<span>join</span> 表<span>2</span> <span>on</span> 连接条件【<span>where</span> 筛选条件】【<span>group</span> <span>by</span> 分组字段】【<span>having</span> 分组后的筛选条件】【<span>order</span> <span>by</span> 排序的字段或表达式】
②好处
语句上,连接条件和筛选条件实现了分离,简洁。
⭐ 注意:左右连接可互换 A left join B 等价于B right join A;内连接是左
右连接的交集;mysql没有外连接。
<span># 用内连接 实现查询所有员工的姓名、工种ID、工种名称</span><span>SELECT</span> a.last_name, a.job_id, b.job_title<span>FROM</span> employees a<span>INNER</span> <span>JOIN</span> jobs b <span>ON</span> a.job_id = b.job_id;
3)连接方式三:自连接
自连接相当于等值连接,但是等值连接涉及多个表,而自连接仅仅是它自己。如下:在员工信息表里,查询员工名和直接上级的名。
<span># 自连接:查询员工名和直接上级的名</span><span>SELECT</span> e.last_name,m.last_name<span>FROM</span> employees e<span>JOIN</span> employees m <span>ON</span> e.<span>`manager_id`</span>=m.<span>`employee_id`</span>;
<span># 等值连接方式</span><span>SELECT</span> e.last_name,m.last_name<span>FROM</span> employees e,employees m <span>WHERE</span> e.<span>`manager_id`</span>=m.<span>`employee_id`</span>;
7、子查询
一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询。在外面的查询语句,称为主查询或外查询。
1)特点
①子查询都放在小括号内
②子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
③子查询优先于主查询执行,主查询使用了子查询的执行结果
④子查询根据查询结果的行数不同分为以下两类:
⭐单行子查询 结果集只有一行 一般搭配单行操作符使用:> < = >= <= 非法使用子查询的情况: a、子查询的结果为一组值 b、子查询的结果为空⭐多行子查询 结果集有多行 一般搭配多行操作符使用:<span>any</span>、all、<span>in</span>、not <span>in</span> <span>in</span>:属于子查询结果中的任意一个就行 <span>any</span>和all往往可以用其他查询代替
2)举栗
<span># 查询位置ID是1700的所有部门人员信息</span><span>SELECT</span> first_name<span>FROM</span> employees<span>WHERE</span> department_id <span>IN</span> ( <span>SELECT</span> department_id <span>FROM</span> departments <span>WHERE</span> location_id = <span>1700</span> )
8、分页查询 (可选)
实际web开发中,当显示的数据,一页显示不完时,需要分页提交sql请求。
1)语法
<span>select</span> 字段|表达式,... <span>from</span> 表名【<span>where</span> 条件】【<span>group</span> <span>by</span> 分组字段】var2=value2【<span>having</span> 条件】【<span>order</span> <span>by</span> 排序的字段】<span>limit</span> 【起始的索引,显示个数】;
2)特点
①起始条目索引默认从0开始
②limit子句放在查询语句的最后
③公式:select * from 表 limit (page-1)*sizePerPage,
sizePerPage:每页显示条目数page:要显示的页数
3)举栗
<span># 查询 员工信息前5条(0可以省略)</span><span>SELECT</span> *<span>FROM</span> employees<span>LIMIT</span> <span>0</span>,<span>5</span>;<span># 查询 员工信息前5-10条</span><span>SELECT</span> *<span>FROM</span> employees<span>LIMIT</span> <span>5</span>,<span>5</span>;
9、union联合查询
union用于把涉及多个表的SELECT语句的结果组合到一个结果集合中。适用于查
询条件较多,多个表之间没有连接关系的场景。
1)语法
<span>select</span> 字段|常量|表达式|函数 【<span>from</span> 表】 【<span>where</span> 条件】 <span>union</span> 【<span>all</span>】<span>select</span> 字段|常量|表达式|函数 【<span>from</span> 表】 【<span>where</span> 条件】 <span>union</span> 【<span>all</span>】.....select 字段|常量|表达式|函数 【<span>from</span> 表】 【<span>where</span> 条件】
2)特点
①多条查询语句的查询的列数必须是一致的
②多条查询语句的查询的列的类型几乎相同
③union 代表去重,union all 代表不去重
3)举栗
<span># 执行下面语句,创建测试数据</span><span># 学生表</span><span>CREATE</span> <span>TABLE</span> <span>`student`</span> ( <span>`id`</span> <span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> AUTO_INCREMENT, <span>`name`</span> <span>varchar</span>(<span>10</span>) <span>DEFAULT</span> <span>NULL</span>, <span>`age`</span> <span>tinyint</span>(<span>4</span>) <span>DEFAULT</span> <span>NULL</span>, <span>`classId`</span> <span>int</span>(<span>11</span>) <span>DEFAULT</span> <span>NULL</span>, PRIMARY <span>KEY</span> (<span>`id`</span>)) <span>ENGINE</span>=<span>InnoDB</span> AUTO_INCREMENT=<span>5</span> <span>DEFAULT</span> <span>CHARSET</span>=utf8;<span>INSERT</span> <span>INTO</span> <span>`student`</span> <span>VALUES</span> (<span>\'1\'</span>, <span>\'s1\'</span>, <span>\'20\'</span>, <span>\'1\'</span>), (<span>\'2\'</span>, <span>\'s2\'</span>, <span>\'22\'</span>, <span>\'1\'</span>),(<span>\'3\'</span>, <span>\'s3\'</span>, <span>\'22\'</span>, <span>\'2\'</span>), (<span>\'4\'</span>, <span>\'s4\'</span>, <span>\'25\'</span>, <span>\'2\'</span>);
<span># 教师表</span><span>CREATE</span> <span>TABLE</span> <span>`teacher`</span> ( <span>`id`</span> <span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> AUTO_INCREMENT, <span>`name`</span> <span>varchar</span>(<span>10</span>) <span>DEFAULT</span> <span>NULL</span>, <span>`age`</span> <span>tinyint</span>(<span>4</span>) <span>DEFAULT</span> <span>NULL</span>, PRIMARY <span>KEY</span> (<span>`id`</span>)) <span>ENGINE</span>=<span>InnoDB</span> AUTO_INCREMENT=<span>4</span> <span>DEFAULT</span> <span>CHARSET</span>=utf8;<span>INSERT</span> <span>INTO</span> <span>`teacher`</span> <span>VALUES</span> (<span>\'1\'</span>, <span>\'t1\'</span>, <span>\'36\'</span>), (<span>\'2\'</span>, <span>\'t2\'</span>, <span>\'33\'</span>), (<span>\'3\'</span>, <span>\'s3\'</span>, <span>\'22\'</span>);
<span># 查询所有学生和教师的id,姓名,年龄</span><span># UNION</span><span>SELECT</span> <span>id</span>, <span>name</span>, age <span>FROM</span> student<span>UNION</span><span>SELECT</span> <span>id</span>, <span>name</span>, age <span>FROM</span> teacher;<span># UNION ALL</span><span>SELECT</span> <span>id</span>, <span>name</span>, age <span>FROM</span> student<span>UNION</span> <span>ALL</span><span>SELECT</span> <span>id</span>, <span>name</span>, age <span>FROM</span> teacher;
UNION 和 UNION ALL 运行结果的区别如下:
⭐ 注意:在多个 SELECT 语句中,第一个 SELECT 语句中被使用的字段名称将被用于结果的字段名称。当使用 UNION 时,MySQL 会把结果集中重复的记录删掉,而使用 UNION ALL ,MySQL 会把所有的记录返回,且效率高于 UNION。
好,今天学习到这里。工作中用的最多就是查询。如果能消化本文涉及到的所有内容,大概能解决80%的工作需求。本文更多的是原理介绍,例子不多,只有先知道是什么,才能知道怎么学。那么,接下来最重要的是要多练习实践。因为实际的业务场景要复杂很多,给大家推荐两个刷题的网站,力扣和牛客网,里面有大量的sql面试题。能进一步提高我们sql的水平。这篇文章主要是SQL的常用查询。明天继续学习SQL的DML增删改。一起加油!