sql语句中的DQL语句
1 查询一个字段
select 字段名 from 表名
select 和 from 都是关键字
字段名和表名都是标识符
强调
对于所有SQl语句来说,是通用的,所有SQL语句都以“;”结尾,另外SQL语句不区分大小写
2 查询两个字段或者多个字段
select 字段名,字段名 from 表名
3 查询所有字段
- 可以把每个字段都写上
- 使用* : 这种方法的使用缺点,效率低,可读性差,在实际开发中不建议,自己玩没问题
4.条件查询
4.1 什么是条件查询
- 不是将所有数据都查出来,二是查询符合条件的
- 语法格式:
select
字段1,字段2,字段3
from
表名
where
条件;
5.分组查询
5.1 什么是分组查询
在实际的应用中,有可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作,这个时候就需要分组查询
select。。。from。。。group by。。。
5.2 将之前的关键字组合在一起,看一下执行顺序
select …
where…
where…
group by…
order by…
以上关键词的执行顺序不能颠倒
- from
- where
- group by
- select
- order by
为什么分组函数不能直接使用在where后面?
分组函数在使用的时候必须先分组之后才能使用,where执行的时候,还没有分组,使用where后面不能出现分组函数
select sum(sal) from emp;
可以执行,因为select,在group by 之后执行。
4.2 条件查询语句
-
=(等号);<>(不等号)
-
between… and…,(>=,<=),使用between … and … 的时候,必须遵循左小右大的原则,而且between … and … 是闭区间,包括两端的值
-
如果要查询值为null的表:要用is,在数据库中null不能使用等号来衡量,要用is null,数据库中的null表示啥也没有,不是一个值,所以不能用等号。
-
and 两个条件限制
-
or 查询两个条件符合的
select empty,ename from emp where job= ‘’ or job = ‘’
- 如果and和or同时出现,那么and的优先级大于or的优先级,解决办法,在or的语句条件加上括号以后在开发中,如果不确定优先级就加小括号就行了
- in 包含,相当于多个or ,not in表示不是这些条件的数据
select empno,ename,job from emp in(‘字段名’,‘字段名’)
- like:模糊查询,支持%或者下划线匹配
% :表示匹配任意多个字符
_:表示任意一个字符
select empno,ename,job from emp like ‘%T’//表示找出以T结尾的数据
select empno,ename,job from emp like ‘K%’//表示找出以K开头的数据
select empno,ename,job from emp like ‘_T%’//表示找出第二个字母是T的
select empno,ename,job from emp like ‘__T%’//表示找出第三个字母是T的
- 由于_在模糊查询中有特殊含义,所以假如我想找出名字中有下划线的,要加上转义字符“\”
6.连接查询
6.1 什么是链接查询
- 从一张表中查询,成为单独查询
- 跨表查询,多张表联合起来进行数据查询,就是连接查询
6.2 连接查询的分类
6.2.1根据年代分类
sql92;sql99(重点99)
6.2.2 根据表链接的方式分类
内连接,外连接
内连接:
- 等值连接
- 非等值连接
- 自连接
外连接:
- 左连接
- 有链接
全连接(no)
6.3 外连接查询
查询每个员工的部门
6.3.1 笛卡尔积现象
两张表链接没有任何条件限制:
select ename,dname from emp,dept;
mysql> select ename,dname from emp,dept;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
| ALLEN | ACCOUNTING |
| ALLEN | RESEARCH |
| ALLEN | SALES |
| ALLEN | OPERATIONS |
| WARD | ACCOUNTING |
| WARD | RESEARCH |
| WARD | SALES |
| WARD | OPERATIONS |
| JONES | ACCOUNTING |
| JONES | RESEARCH |
| JONES | SALES |
| JONES | OPERATIONS |
| MARTIN | ACCOUNTING |
| MARTIN | RESEARCH |
| MARTIN | SALES |
| MARTIN | OPERATIONS |
| BLAKE | ACCOUNTING |
| BLAKE | RESEARCH |
| BLAKE | SALES |
| BLAKE | OPERATIONS |
| CLARK | ACCOUNTING |
| CLARK | RESEARCH |
| CLARK | SALES |
| CLARK | OPERATIONS |
| SCOTT | ACCOUNTING |
| SCOTT | RESEARCH |
| SCOTT | SALES |
| SCOTT | OPERATIONS |
| KING | ACCOUNTING |
| KING | RESEARCH |
| KING | SALES |
| KING | OPERATIONS |
| TURNER | ACCOUNTING |
| TURNER | RESEARCH |
| TURNER | SALES |
| TURNER | OPERATIONS |
| ADAMS | ACCOUNTING |
| ADAMS | RESEARCH |
| ADAMS | SALES |
| ADAMS | OPERATIONS |
| JAMES | ACCOUNTING |
| JAMES | RESEARCH |
| JAMES | SALES |
| JAMES | OPERATIONS |
| FORD | ACCOUNTING |
| FORD | RESEARCH |
| FORD | SALES |
| FORD | OPERATIONS |
| MILLER | ACCOUNTING |
| MILLER | RESEARCH |
| MILLER | SALES |
| MILLER | OPERATIONS |
+--------+------------+
56 rows in set (0.00 sec)
当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为笛卡尔积现象(一个数学现象)
6.3.2 如何避免笛卡尔积现象
连接时,添加条件闲着;
select ename,dname from emp,dept where emp.deptno = dept.deptno;
mysql> select ename,dname from emp,dept where emp.deptno = dept.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
14 rows in set (0.00 sec)
- 这样写避免了笛卡尔积现象,但是匹配次数没有减少,仍然是56次,只不过进行了四选一
select emp.ename,dept.dname from emp,dept where emp.deptno = dept.deptno;
给表起别名(这是92语法)
select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;
通过笛卡尔积现象得出,连接的表越多效率越低,尽量避免表的连接
6.3.3 内连接的等值连接
仍然是查询每个员工所在的部门名称
select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;
这是99语法
相较于92语法来说,99语法结构更清晰一点,
sql99的一个优点是:表连接的条件是独立的,连接之后,如果还想继续筛选,可以在后面继续添加where
select
e.ename,d.dname
from
emp e
inner join //inner是可以省略的,但是带上可以一言就看出来这是一个内连接(可读性更好)
dept d
on
e.deptno = d.deptno;//这个条件是一个等量关系,所以被称为等值连接
6.3.4 内连接的非等值连接
案例:找出每个员工的薪资等级,要求显示员工名,薪资,薪资等级
条件不是一个等量关系,称为非等值连接
select e.ename,e.sal,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
mysql> select e.ename,e.sal,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
+--------+---------+-------+
| ename | sal | grade |
+--------+---------+-------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
14 rows in set (0.00 sec)
6.3.5内连接的自连接
案例:查询每个员工的领到
技巧:吧一张表看做两张表
select a.ename as ‘员工名’ ,b.ename as ‘领导名’ from emp a join emp b on a.mgr = b.empno;
mysql> select a.ename as '员工名' ,b.ename as '领导名' from emp a join emp b on a.mgr = b.empno;
+--------+--------+
| 员工名 | 领导名 |
+--------+--------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+--------+
13 rows in set (0.00 sec)
6.4 外连接
如果有额外需求:比如包括没有匹配的也要查出来:
select e.ename,d.dname from emp e right join dept d on e.deptno = d.deptno;//这是一个右外连接,right代表:将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表
mysql> select e.ename,d.dname from emp e right join dept d on e.deptno = d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
| NULL | OPERATIONS |
+--------+------------+
15 rows in set (0.01 sec)
带有right的是右外连接,又叫做右连接,带有left的是左连接,任何一个右连接都有左连接的写法,任何一个左连接都有右连接的写法
外连接在join前面有一个outer,但是可以省略
外连接的查询结果条数一定>=内连接的查询结果
案例:查询每个员工的上级领导,要求显示所有的员工和领导名字
select a.empno,a.ename,b.ename from emp a left join emp b on a.mgr = b.empno;
mysql> select a.empno,a.ename,b.ename from emp a left join emp b on a.mgr = b.empno;
+-------+--------+-------+
| empno | ename | ename |
+-------+--------+-------+
| 7369 | SMITH | FORD |
| 7499 | ALLEN | BLAKE |
| 7521 | WARD | BLAKE |
| 7566 | JONES | KING |
| 7654 | MARTIN | BLAKE |
| 7698 | BLAKE | KING |
| 7782 | CLARK | KING |
| 7788 | SCOTT | JONES |
| 7839 | KING | NULL |
| 7844 | TURNER | BLAKE |
| 7876 | ADAMS | SCOTT |
| 7900 | JAMES | BLAKE |
| 7902 | FORD | JONES |
| 7934 | MILLER | CLARK |
+-------+--------+-------+
14 rows in set (0.02 sec)
6.5 三张表或者四张表链接
语法:
select … from a join b on a和b的连接条件 join c on a和c的连接条件 join d on a和d的连接条件
案例:找出每个员工的部门名称以及工资等级,要求系那是员工名,部门名,薪资,薪资低等级
select e.ename,d.dname,e.sal,s.grade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal;
mysql> select e.ename,d.dname,e.sal,s.grade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal;
+--------+------------+---------+-------+
| ename | dname | sal | grade |
+--------+------------+---------+-------+
| SMITH | RESEARCH | 800.00 | 1 |
| ALLEN | SALES | 1600.00 | 3 |
| WARD | SALES | 1250.00 | 2 |
| JONES | RESEARCH | 2975.00 | 4 |
| MARTIN | SALES | 1250.00 | 2 |
| BLAKE | SALES | 2850.00 | 4 |
| CLARK | ACCOUNTING | 2450.00 | 4 |
| SCOTT | RESEARCH | 3000.00 | 4 |
| KING | ACCOUNTING | 5000.00 | 5 |
| TURNER | SALES | 1500.00 | 3 |
| ADAMS | RESEARCH | 1100.00 | 1 |
| JAMES | SALES | 950.00 | 1 |
| FORD | RESEARCH | 3000.00 | 4 |
| MILLER | ACCOUNTING | 1300.00 | 2 |
+--------+------------+---------+-------+
14 rows in set (0.01 sec)
案例:找出每个员工的部门名称以及工资等级,要求显示员工名,领导名,部门名,薪资,薪资等级
select e.ename,d.dname,e.sal,s.grade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal left join emp l on e.mgr = l.empno;
mysql> select e.ename,d.dname,e.sal,s.grade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal left join emp l on e.mgr = l.empno;
+--------+------------+---------+-------+
| ename | dname | sal | grade |
+--------+------------+---------+-------+
| SMITH | RESEARCH | 800.00 | 1 |
| ALLEN | SALES | 1600.00 | 3 |
| WARD | SALES | 1250.00 | 2 |
| JONES | RESEARCH | 2975.00 | 4 |
| MARTIN | SALES | 1250.00 | 2 |
| BLAKE | SALES | 2850.00 | 4 |
| CLARK | ACCOUNTING | 2450.00 | 4 |
| SCOTT | RESEARCH | 3000.00 | 4 |
| KING | ACCOUNTING | 5000.00 | 5 |
| TURNER | SALES | 1500.00 | 3 |
| ADAMS | RESEARCH | 1100.00 | 1 |
| JAMES | SALES | 950.00 | 1 |
| FORD | RESEARCH | 3000.00 | 4 |
| MILLER | ACCOUNTING | 1300.00 | 2 |
+--------+------------+---------+-------+
14 rows in set (0.00 sec)
7.子查询
7.1 什么是子查询
select语句中嵌套select语句,被嵌套的select语句成为子查询
7.2 子查询都可以出现在哪里
select
…(select)
from
…(select)
where
…(select)
7.3 where语句中的子查询
案例:找出比最低工资高的员工的姓名和工资
select ename,sal from emp where sal > (select min(sal) from emp);
mysql> select ename,sal from emp where sal > (select min(sal) from emp);
+--------+---------+
| ename | sal |
+--------+---------+
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
13 rows in set (0.00 sec)
优先执行子查询
7.4 from语句下的子查询
注意:from后面的每个子查询又可以将子查询的结果当做一张临时表。(技巧)
案例:找出每个岗位的平均工资的薪资等级
select job,avg(sal) from emp group by job;
select t.*,s.grade from (select job,avg(sal) as avgsal from emp group by job) t join salgrade s on t.avgsal between s.losal and s.hisal;
mysql> select t.*,s.grade from (select job,avg(sal) as avgsal from emp group by job) t join salgrade s on t.avgsal between s.losal and s.hisal;
+-----------+-------------+-------+
| job | avgsal | grade |
+-----------+-------------+-------+
| CLERK | 1037.500000 | 1 |
| SALESMAN | 1400.000000 | 2 |
| ANALYST | 3000.000000 | 4 |
| MANAGER | 2758.333333 | 4 |
| PRESIDENT | 5000.000000 | 5 |
+-----------+-------------+-------+
5 rows in set (0.01 sec)
7.5 在select后面出现的子查询
select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
mysql> select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
- 对于select后面的子查询只能一次返回一条结果,多余一条就报错
7.6union合并查询结果
案例:查询工作岗位是MANAGER和SALESMAN的员工
select ename,job from emp where job = ‘MANAGER’
union
select ename,job from emp where job = ‘SALESMAN’;
mysql> select ename,job from emp where job = 'MANAGER'
->
-> union
->
-> select ename,job from emp where job = 'SALESMAN';
+--------+----------+
| ename | job |
+--------+----------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.01 sec)
union的效率要高一些。对于表连接来说,每一次新表,则匹配的次数满足笛卡尔积爱,成倍的翻。。。但是union可以见识匹配次数,在减少匹配次数的情况了,号可以完成两个结果的拼接。
a 表连接 b 连接 c
- 使用表连接需要1000次
- 使用union a连接b a连接c 需要200次
union相当于是吧乘法变成了加法
7.7 union使用的注意事项
select ename,job from emp where job = ‘MANAGER’
union
select ename from emp where job = ‘SALESMAN’;
这样写会报错,union在合并的时候,要求两个结果列数相同
select ename,job from emp where job = ‘MANAGER’
union
select ename,sal from emp where job = ‘SALESMAN’;
这样写mysql可以,但是oracl会报错,合并时,数据类型也要相同
7.8 limit的使用
案例:按照薪资降序,取排在前5的员工
select
ename,sal
from
emp
order by
sal desc
limit 0,5;
mysql> select
->
-> ename,sal
->
-> from
->
-> emp
->
-> order by
->
-> sal desc
->
-> limit 5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.01 sec)
- 完整用法:limit startIndex length//startIndex表示起始下标 length是长度
- 缺省用法:limit length //默认下标从0开始
需要注意的是:limit在order by之后执行