mysql 数据查询全讲
数据查询 涉及到DQL(Data Query Language)是sql语句的一类
本文全面介绍了mysql下 select 语句的各种查询方式:普通查询,模糊查询,查询排序,分页查询,聚合函数查询 ,分组查询,子查询,连接查询(内连接 外连接) 组合查询。
每一条 select 语句都经过测试,没嘛哒!
创建两个表作为实验对象:
create table dept
(
deptno int primary key, -- 部门号
dname nvarchar(30), -- 部门名称
loc nvarchar(30) -- 部门所在地点
);
create table emp
(
empno int primary key , -- 员工编号
ename nvarchar(30), -- 员工姓名
job nvarchar(30), -- 员工职位
mgr int, -- 员工领导的员工编号
hiredate datetime, -- 入职日期
sal numeric(10,2), -- 薪水
comm numeric(10,2), -- 奖金
deptno int foreign key references dept(deptno) -- 员工所在部门的编号 与部门表通过外键关联
);
MySQL 8 不允许这样创建外键,要将创建员工部门编号项与创建外键分开两句:
deptno int,
foreign key (deptno) references dept(deptno)
在表中插入相应的数据
insert into dept values(10,'accounting','newyork');
insert into dept values(20,'research','dallas');
insert into dept values(30,'sales','chicago');
insert into dept values(40,'operations','boston');
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7934,'miller','clerk',7782,'1982-1-23',1300.00,10);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7369,'smith','clerk',7902,'1980-12-17',800.00,20);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7566,'jones','manager',7839,'1981-4-2',2975.00,20);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7698,'blake','manager',7839,'1981-5-1',2850.00,30);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7782,'clark','manager',7839,'1981-6-9',2450.00,10);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7788,'scott','analyst',7566,'1987-4-19',3000.00,20);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7876,'adams','clerk',7788,'1987-5-23',1100.00,20);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7900,'james','clerk',7698,'1981-12-3',950.00,30);
insert into emp (empno,ename,job,mgr,hiredate,sal,deptno)values(7902,'ford','analyst',7566,'1981-12-3',3000.00,20);
insert into emp (empno,ename,job,hiredate,sal,deptno)values(7839,'king','president','1981-11-17',5000.00,10);
insert into emp values(7499,'allen' ,'salesman',7698,'1981-2-20',1600.00,300.00 ,30);
insert into emp values(7521,'ward' ,'salesman',7698,'1981-2-22',1250.00,500.00 ,30);
insert into emp values(7844,'turner','salesman',7698,'1981-9-8' ,1500.00,0.00 ,30);
insert into emp values(7654,'martin','salesman',7698,'1981-9-28',1250.00,1400.00,30);
查询语句————> select 语句的结构分析:
select distinct [字段名] from [(左)表名] [连接类型] join [(右)表名] on [连接条件]
where [查询条件] group by [字段名(按该字段分组)] having [分组删选条件]
order by [字段名(按该字段排序)] [asc/desc(排序方式)] limit [分页条件]
select语句执行顺序:
-- (7) SELECT
-- (8) DISTINCT <select_list>
-- (1) FROM <left_table>
-- (3) <join_type> JOIN <right_table>
-- (2) ON <join_condition>
-- (4) WHERE <where_condition>
-- (5) GROUP BY <group_by_list>
-- (6) HAVING <having_condition>
-- (9) ORDER BY <order_by_condition>
-- (10) LIMIT <limit_number>
-- 1、 FORM: 对FROM左边的表和右边的表计算笛卡尔积,产生虚表VT1。
-- 2、 ON: 对虚表VT1进行ON过滤,只有那些符合<join-condition>的行才会被记录在虚表VT2中。
-- 3、 JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3。
-- 4、 WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。
-- 5、 GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5。
-- 6、 HAVING: 对虚拟表VT5应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT6中。
-- 7、 SELECT: 执行select操作,选择指定的列,插入到虚拟表VT7中。
-- 8、 DISTINCT: 对VT7中的记录进行去重。产生虚拟表VT8.
-- 9、 ORDER BY: 将虚拟表VT8中的记录按照<order_by_list>进行排序操作,产生虚拟表VT9.
-- 10、 LIMIT: 取出指定行的记录,产生虚拟表VT10, 并将结果返回。
说明:网上给出的资料大都是这个顺序,但本人觉得应将 2,3 的顺序调换,尤其涉及到左连接和右连接的时候,根据连接类型,使用连接条件:若是内连接,排除不匹配的行;若是左连接,保留左表数据,排选右表数据;右连接则反之。(个人理解,大家多加批评指正)。
查询从这里开始:
普通查询
-- 从表中查询所有记录 ,*表示在结果中显示全部字段信息 。
select * from emp;
-- 从 emp 表中查询 sal, job , deptno 三个字段。
select sal,job,deptno from emp;
-- distinct 关键字 表示重复的结果只显示一条。
select distinct deptno from emp;
-- 查询员工名称和其年工资, comm为NULL是用 0 计算。对IFNULL(exp1,exp2)函数,如果exp1的值为NULL 则显示exp2;否则显示exp1.
select ename,sal*13+IFNULL(comm,0)*13 as '年工资' from emp;
-- 显示在 1982-1-1 之后入职的人员 。where 关键字后跟查询条件。
select *from emp where hiredate >'1982-1-1';
-- 显示工资 sal 在2000 和 3000 之间 ( between and ) 。
select *from emp where sal between 2000 and 3000;
-- 查询最高的领导- 最高领导之上再没有领导 所以 mgr 字段为null.
select *from emp where mgr is null;
模糊查询
-- 查询ename 是 字母 j 开头 同时要么是管理员 要么 sal 在 500 以上
-- like 后面的条件是一个模糊查询,'%' 匹配多个字符,'_'匹配一个字符 ,or 表示选择条件查询——或者
select *from emp where (sal > 500 or job = 'manager' ) and ename like 'j%';
查询排序
-- 按员工薪资排序
-- order by sal 表示按照 sal 来排序, desc 表示降序,换成 asc 便表示升序
select *from emp order by sal desc;
-- 按照部门号的升序而员工工资的降序排列
select * from emp order by deptno asc ,sal desc;
分页查询:limit
-- mysql 提供了 关键字 limit 可以实现分页查询, limit 后面可以跟 两个数字作为参数,第一个数字表示从第几行起开始查询,
-- 第二个数字表示查询多少条记录,当记录数小于该数字时全部显示。当第一个数字为 0 (零)时可以略去不写。下面这两条查询语句的结果是一样的。
select * from emp limit 4;
select * from emp limit 0,4;
聚合函数查询: 聚合函数最大的特点就是能够根据一组数据求出一个值
-- 查询平均工资和工资总和
select avg(sal) 平均工资, sum(sal) 总工资 from emp;
-- 查询工资高于平均工资的员工姓名-- 这里用到了子查询(下面有讲)
select ename , sal,(select avg(sal) from emp) 平均工资 from emp where sal > (select avg(sal) from emp);
分组查询: group by
-- 查询每个部门的平均工资和最高工资
select avg(sal) ,max(sal),deptno from emp group by deptno;
-- 显示每个部门的每种岗位的平均工资 按照部门号 和 职位 两个字段进行分组
-- mysql 会先按照 deptno进行分组,然后在每一个组中再按 job 分组
select avg(sal) , min(sal) ,deptno , job from emp group by deptno ,job order by deptno;
要求:显示平均工资低于两千的部门号 和它的平均工资
-- 第一步: 查询每个部门的平均工资,并显示它的部门号
-- 第二步:将其中平均工资低于 2000 的结果删选出来 having vv < 2000;
-- 说明: having 往往和group by 结合使用, 可以分组查询结果进行筛选
-- having 子句往往包含聚合函数(所谓聚合函数,其最大的特点就是能够根据一组数据求出一个值)
-- where 也是对结果进行筛选,但where子句中不能包含聚合函数,where子句也往往是在分组和聚合运算之前
-- 对输入行进行筛选,可以作用于表或视图
-- having子句是在分组和聚合运算之后对其结果进行筛选,作用于组。这里 vv 只是取了一个别名。
select avg(sal) vv , deptno from emp group by deptno having vv > 2000 order by vv asc;
子查询
-- 嵌入在其他sql语句中的select语句
-- where 语句使用子查询
-- 要求:显示与Smith同一部门的员工 (在where 语句中使用子查询)
-- 若子查询返回的是多行结果,= 号就要改成关键字 in
-- 当然 根据需求 还可以使用 not in 或其他比较运算符:= <> < > != ....(当然,若子查询返回结果是多行,则不能使用比较运算符)
select *from emp where deptno=(select deptno from emp where ename='smith');
-- 显示其他部门中与10号部门职位一样的员工信息
select * from emp where job in(select job from emp where emp.deptno='') and deptno <> '';
-- 带 exists 关键字的子查询
-- 使用 exists 关键字时, 内层查询语句不返回查询的记录,而是根据是否有记录满足查询条件返回一个真价值(true/false)
-- 当返回值为 true 时外层查询语句正常执行,否则外层查询语句不执行查询或查询不出任何记录;
-- not exists 的作用于exists 刚好相反
select * from emp where exists (select ename from emp where empno = '');
-- 带 any 的子查询
-- any 表示任意一个
-- 它允许创建一个表达式,对子查询的返回值列表,进行比较,只要满足内层子查询中的,任意一个比较条件,就返回一个结果作为外层查询条件
-- 如果将 any 换成 all 情况就刚好相反,就要满足全部的条件才行
select * from emp where sal >= any(select avg(sal) from emp group by deptno);
在 from 语句中使用子查询
-- 要求: 显示高于部门平均工资的员工信息
-- 第一步:查询每个部门的平均工资:select avg(sal) avgsal,deptno from emp e group by deptno
-- 第二步:将上面的查询结果作为临时表,利用内连接(下面有讲)
select * from emp e natural join (select avg(sal) avgsal,deptno from emp e group by deptno) temp where e.sal > temp.avgsal;
select * from emp e inner join
(select avg(sal) avgsal,deptno from emp e group by deptno) temp
on e.deptno=temp.deptno where e.sal > temp.avgsal;
连接查询: 主要有内连接和外连接(内连接、外连接都是在交叉连接的基础上根据连接条件删选的)
内连接 内联接使用比较运算符根据构成连接的表共有的列的值匹配它们的行,不匹配的行将被排除
-- cross join 叫做交叉连接 加上限制条件e.deptno=d.deptno 便是等同连接, 等同连接又叫作 等值连接 是内连接最常见的例子;以下四个 sql 语句是等价的
-- count(*) 是一个聚合函数,表示求记录数
select count(*) from emp e cross join dept d where e.deptno=d.deptno ;
select count(*) from emp e , dept d where e.deptno=d.deptno ;
select count(*) from emp e inner join dept d where e.deptno=d.deptno ;
select count(*) from emp e inner join dept d on e.deptno=d.deptno ;
自然连接
-- 自然连接无需指定连接列,SQL会检查两个表中是否相同名称的列,
-- 且直接在连接条件中使用,并且在连接条件中仅包含一个连接列。不允许使用ON语句
select e.ename,d.dname from emp e natural join dept d;
自连接
-- 显示每个员工的姓名和他的上级领导的名字
-- 自连接 就是在需要的时候将一张表看作两张,进行自己的两个字段匹配
select worker.ename as worker, boss.ename as boss from emp worker inner join emp boss on worker.mgr=boss.empno;
左连接(外连接:左连接,右连接)
-- 上面的自连接实现中 对于员工 king 没有匹配的内容,所以查询结果是 13 条记录
-- 与内连接不同,左外连接还返回左表中不符合连接条件但却符合查询条件的数据行,也就是说左边表显示满足查询条件所有数据,右边表数据数据少了补NULL值,数据多了不显示;关键字outer 可以略去。
select worker.ename as worker, boss.ename as boss from emp worker left outer join emp boss on worker.mgr=boss.empno;
右连接: 与左连接刚好对称。
组合查询 : 通过组合查询可以实现传说中的全连接
-- union 关键字用于将多条 select 语句返回的结果集合并成一个结果集
-- union 将所有的查询结果合并到一起,排除重复记录,并默认排序
-- union all 将所有的查询结果合并到一起,保留重复记录,不排序
-- 组合查询 多用于以下情况:
-- 1.从多个表中查询出相似结构的数据,并且返回一个结果集
-- 2.从单个表中多次SELECT查询,将结果合并成一个结果集返回。注意:排序的字段前面不能带表名,并且是两个select语句中共有的字段
(select ee.empno,ee.ename,ee.job,ee.sal, ee.comm from emp ee where ee.sal > 1500)
union
(select e.empno,e.ename,e.job,e.sal,e.comm from emp e where e.comm is not null) order by sal;
-- 上面的两条select 语句通过 union 组合, 将结果合并输出。这条组合查询也可用 where 条件来完成。
select e.empno,e.ename,e.job,e.sal, e.comm from emp e where( e.sal > 1500) or (e.comm is not null);
组合查询与 where
-- 一般: 能用where来实现的都可以用 union 来实现,而能用 union 实现的where却不一定能实现 例如 用union all 合并后会有重复记录
-- 1. union 必须由两条或更多的 select 语句组成,语句之间用 union 连接
-- 2. union 中的每个select语句必须包含相同的列、表达式或聚合函数,它们的出现顺序可以不一致(这里指查询相同的字段,表可以不一样)
-- 3. 列的数据类型必须相同(或兼容,兼容不提倡)
组合查询排序
-- 1. 只能使用一条 order by 子句,并且只能放在最后一条 select 语句后面
-- 2. 必须使用共同的字段名
-- 3. 不能带表名,哪怕表名相同
(select empno,ename as '名字',job,sal, comm from emp where sal > 1500)
union
(select empno,ename,job,sal,comm from emp where comm is not null) order by sal;
-- 多表组合查询时 select 语句中显示的字段名可能不一样 但显示的结果却是第一条 select 语句中的字段名
-- 可以通过 在 sql 语句中加入 '表名的别名' as tableName 提供新的一列 区分数据来自 哪张表.
(select empno,ename as '名字',job,sal, comm ,'first' as tableName from emp where sal > 1500)
union
(select empno,ename,job,sal,comm, 'second' as tableName from emp where comm is not null) order by sal;
foreign key references dept(deptno)
mysql 数据查询全讲的更多相关文章
- MySQL数据查询之多表查询
多表查询 多表联合查询 #创建部门 CREATE TABLE IF NOT EXISTS dept ( did int not null auto_increment PRIMARY KEY, dna ...
- MySQL - 数据查询 - 简单查询
1. 简述 查询数据是指从数据库中获取所需要的数据.如Jack 要达到验证用户名和密码的目的,就需要从数据库已保存的用户表中读取当前用户的密码进行验证,以验明正身!保存查询数据是数据库操作中常用且重要 ...
- nodejs mysql 数据查询例子
1.安装nodejs 2.安装mysql npm包 地址:https://github.com/felixge/node-mysql npm install mysql 3.相应API查看及调用: ...
- MySQL数据查询之单表查询
单表查询 简单查询 - 创建表 DROP TABLE IF EXISTS `person`; CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMEN ...
- MySQL数据以全量和增量方式,同步到ES搜索引擎
本文源码:GitHub·点这里 || GitEE·点这里 一.配置详解 场景描述:MySQL数据表以全量和增量的方式向ElasticSearch搜索引擎同步. 1.下载内容 elasticsearch ...
- 【初学python】使用python连接mysql数据查询结果并显示
因为测试工作经常需要与后台数据库进行数据比较和统计,所以采用python编写连接数据库脚本方便测试,提高工作效率,脚本如下(python连接mysql需要引入第三方库MySQLdb,百度下载安装) # ...
- Packets larger than max_allowed_packet are not allowed(mysql数据查询提示:不允许超过允许的最大数据包)解决方案
问题背景: 首先我的项目运用的时Mysql,在做一个数据更新操作的时候,提示异常:System.Exception:“ExecuteNonQuery:Packets larger than max_a ...
- MySQL数据查询
数据查询语言DQL select [all | distinct] 字段或表达式列表 [from子句] [where子句] [group by子句] [having子句] [order by子句] [ ...
- MySql数据查询的逻辑蕴含条件问题
SQL语言中没有蕴含逻辑运算.但是,可以利用谓词演算将一个逻辑蕴含的谓词等价转换为:p->q ≡┐p∨q. 我们通过一个具体的题目来分析:(具体的表和数据详见文章:Mysql数据库中的EXIST ...
随机推荐
- Oracle 11.2.0.4.0 Dataguard部署和日常维护(3)-Datauard监控篇
1. v$database 查看当前数据库的角色和保护模式 primary库查看 column NAME format a10 column PROTECTION_MODE format a2 ...
- 基数排序模板[luogu 1177]
#include<bits/stdc++.h> #define LL long long using namespace std; ,bas=; ]; LL idx(LL k,LL w) ...
- Linux五种IO模型(同步 阻塞概念)
Linux五种IO模型 同步和异步 这两个概念与消息的通知机制有关. 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.比如,调用readfrom系统调用时,必须等待IO操 ...
- 自签名证书说明——自签名证书的Issuer和Subject是一样的。不安全的原因是:没有得到专业SSL证书颁发的机构的技术支持?比如使用不安全的1024位非对称密钥对,有效期设置很长等
一般的数字证书产品的主题通常含有如下字段:公用名称 (Common Name) 简称:CN 字段,对于 SSL 证书,一般为网站域名:而对于代码签名证书则为申请单位名称:而对于客户端证书则为证书申请者 ...
- 把旧系统迁移到.Net Core 2.0 日记(7) Tag Helpers /ResponseCache
Tag Helpers是Html Helpers的一种替换 比如,原来的视图模型定义是这样的: @using (Html.BeginForm("Register", "A ...
- windows mfc 程序,不同程序通信和互斥
1. 共享内存(项目中使用过) 我转备份文章:http://www.cnblogs.com/swing07/p/8087686.html CreateFileMapping 或 OpenFileMap ...
- sigmoid belief network boltszmann machine
because of explaining away, the hidden weights in sigmoid belief network is no longer independent
- Linux第八周作业
一 理解编译链接的过程和ELF可执行文件格式 这张图说明了可执行程序的产生 大致过程为 .c文件汇编成汇编代码.asm, 然后再汇编成目标码.o, 然后链接成可执行文件a.out, 这时可执行文件就可 ...
- shell脚本分析二
Shell 基本运算符Shell 和其他编程语言一样,支持多种运算符,包括: 算数运算符 关系运算符 布尔运算符 字符串运算符 文件测试运算符原生bash不支持简单的数学运算,但是可以通过其他命令来实 ...
- 微信和支付宝支付模式详解及实现(.Net标准库)
支付基本上是很多产品都必须的一个模块,大家最熟悉的应该就是微信和支付宝支付了,不过更多的可能还是停留在直接sdk的调用上,甚至和业务系统高度耦合,网上也存在各种解决方案,但大多形式各异,东拼西凑而成. ...