查询结果
关于查询结果集的去重?(distinct关键字去除重复记录)
mysql> select distinct job from emp;
+———–+
| job |
+———–+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+———–+
select ename,distinct job from emp;
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。
mysql> select distinct deptno,job from emp order by deptno;
+——–+———–+
| deptno | job |
+——–+———–+
| 10 | CLERK |
| 10 | MANAGER |
| 10 | PRESIDENT |
| 20 | ANALYST |
| 20 | CLERK |
| 20 | MANAGER |
| 30 | CLERK |
| 30 | MANAGER |
| 30 | SALESMAN |
+——–+———–+
案例:统计岗位的数量?
mysql> select count(distinct job) from emp;**
+———————+
| count(distinct job) |
+———————+
| 5 |
+———————+
1 row in set (0.00 sec)
连接查询
什么是连接查询?
在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。
在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
在实际上数据会存在大量的重复,导致数据的冗余。
连接查询的分类
根据语法出现的年代来划分的,包括:
SQL 92(一些老的DBA可能还在使用这种语法。DBA:Database Administrator)
SQL 99(比较新的语法)
根据表的连接方式来划分,包括:
- 内连接:
等值连接
非等值连接
自连接 - 外连接:
左外连接(左连接)
右外连接(右连接) - 全连接(很少用)
在表的连接查询方面有一种现象被称为:笛卡尔积现象
案例:找出每一个员工的部门名称,要求显示员工名和部门名
mysql> select ename,deptno from emp;
+——–+——–+
| ename | deptno |
+——–+——–+
| SMITH | 20 |
| ALLEN | 30 |
| WARD | 30 |
| JONES | 20 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| SCOTT | 20 |
| KING | 10 |
| TURNER | 30 |
| ADAMS | 20 |
| JAMES | 30 |
| FORD | 20 |
| MILLER | 10 |
+——–+——–+mysql> select * from dept
-> ;
+——–+————+———-+
| DEPTNO | DNAME | LOC |
+——–+————+———-+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |select ename,dname from emp,dept;
mysql> select ename,dname from emp,dept;//ename和dname要联合起来一块显示,黏到一块。
+——–+————+
| 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)
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数两张表记录条数的乘积。
关于表的别名:
select e.ename, d.dname from emp e, dept d;
表的别名有什么好处
第一:执行效率高
第二:可读性好
怎么避免笛卡尔积现象?
思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
不会,次数还是56此。只不过显示的是有效记录
案例:找出每一个员工的部门名称,要求显示员工名和部门名。
mysql> select e.ename,d.dname from emp e, dept d where e.deptno=d.deptno;
+——–+————+
| 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)
内连接之等值连接
特点:条件是等量关系
案例:查询每个员工的部门名称,要求显示员工名和部门名
SQL92:(太老,不用了)
select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno;
SQL99:(常用的)
select
e.ename, d.dname
from
emp e
join
dept d
on **
**e.deptno = d.deptno; //等值连接select
e.ename, d.dname
from
emp e
inner join // inner可省略
dept d
on **
**e.deptno = d.deptno; //等值连接
SQL99语法结构更清晰一些:表的连接条件和后来的where条件分离了
内连接之非等值连接
最大的特点是:连接条件中的关系是非等量关系。
案例:找出每个员工的工资等级,要求显示员工名、工资、工资等级。
select
e.ename, e.sal, s.grade
from
emp e
join salgrade s
on
e.sal>=losal and e.sal<=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)
内连接之自连接
最大的特点:一张表看做两张表。自己连接自己。
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
select
a.ename, b.ename
from
emp a
inner join
emp b
on
a.mgr=b.deptno;
外连接
什么是外连接,和内连接有什么区别?
内连接:假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
AB两张表没有主副之分,两张表是平等的。
外连接:假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
外连接的分类?
左外连接(左连接):表示左边的这张表是主表。
右外连接(右连接):表示右边的这张表是主表。
左连接有有连接的写法,右连接也会有对应左连接的写法
案例:找出每个员工的上级领导?(所有员工必须全部查询出来)
//inner可以省略
内连接
select a.ename, b.ename from emp a inner join emp b on a.mgr=b.empno;//outer可以省略
外连接(左连接)
select a.ename, b.ename from emp a left outer join emp b on a.mgr=b.empno;外连接(右连接)
select a.ename, b.ename from emp b right outer join emp a on a.mgr=b.empno;
外连接重要的特点是:主表的数据无条件的全部查询出来
案例:找出那个部门没有员工?
mysql> select d.* from emp e right join dept d on e.deptno=d.deptno where e.empno is null;
+——–+————+——–+
| DEPTNO | DNAME | LOC |
+——–+————+——–+
| 40 | OPERATIONS | BOSTON |
+——–+————+——–+
1 row in set (0.00 sec)
三张表怎么连接查询?
案例:找出每一个员工的部门名称以及工资等级
//全部员工
select * from emp;
//部门名称
select e.ename, d.dname from emp e join dept d on e.deptno=d.deptno;
//工资等级
select e.ename, s.grade from emp e join salgrade s on e.sal between losal and hisal;
//最终结合
select e.ename, d.dname, s.grade from emp e join dept d on e.deptno=d.deptno join salgrade s on e.sal between losal and hisal;
案例:找出每个员工的部门名称、工资等级、以及上级领导。
select e.ename, d.dname, s.grade,b.ename from emp e join dept d on e.deptno=d.deptno join salgrade s on e.sal between losal and hisal join emp b on e.mgr=b.empno;
子查询
什么是子查询?子查询都可以出现在哪里?
select 语句当中嵌套select语句,被嵌套的select语句是子查询
子查询可以出现在哪里?
select
..(select)
from
..(select)
where
..(select)
where子句中使用子查询
案例:找出高于平均薪资的员工信息。
select * from emp where sal > (select avg(sal) from emp);
From后面嵌套子查询
案例:找出每个部门平均薪水的薪资等级
First Step:
select avg(sal) avg, deptno from emp group by deptno;+————-+——–+
| avg | deptno |
+————-+——–+
| 2916.666667 | 10 |
| 2175.000000 | 20 |
| 1566.666667 | 30 |
+————-+——–+
3 rows in set (0.00 sec)Second Step:
select n.avg, n.deptno, s.grade from (select avg(sal) avg, deptno from emp group by deptno) n join salgrade s on n.avg between losal and hisal;+————-+——–+——-+
| avg | deptno | grade |
+————-+——–+——-+
| 2916.666667 | 10 | 4 |
| 2175.000000 | 20 | 4 |
| 1566.666667 | 30 | 3 |
+————-+——–+——-+
3 rows in set (0.01 sec)
案例:找出每个部门平均的薪水等级
First Step:
select e.deptno, s.grade from emp e join salgrade s on e.sal between losal and hisal;+——–+——-+
| deptno | grade |
+——–+——-+
| 20 | 1 |
| 30 | 3 |
| 30 | 2 |
| 20 | 4 |
| 30 | 2 |
| 30 | 4 |
| 10 | 4 |
| 20 | 4 |
| 10 | 5 |
| 30 | 3 |
| 20 | 1 |
| 30 | 1 |
| 20 | 4 |
| 10 | 2 |
+——–+——-+
14 rows in set (0.00 sec)Second Step:
select s.deptno, avg(s.grade) avg from (select e.deptno, s.grade from emp e join salgrade s on e.sal between losal and hisal) s group by s.deptno;
+——–+——–+
| deptno | avg |
+——–+——–+
| 10 | 3.6667 |
| 20 | 2.8000 |
| 30 | 2.5000 |
+——–+——–+
3 rows in set (0.00 sec)
在select后面嵌套子查询
案例:找出每个员工所在的部门名称,要求显示员工名和部门名。
select e.ename, (select d.dname from dept d where e.deptno=d.deptno) 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 |
+——–+————+
union(可以将查询结果集相加)
案例:找出工作岗位是SALESMAN和MANAGER的员工
mysql> select * from emp where job=’salesman’ or job=’manager’;
+——-+——–+———-+——+————+———+———+——–+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+——-+——–+———-+——+————+———+———+——–+
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
First Step:
select * from emp where job=’salesman’ or job=’manager’;
Second Step:
select * from emp where job in(‘salesman’ ,’manager’) ;Third Step: union
select * from emp where job=’salesman’
union
select * from emp where job=’manager’;+——-+——–+———-+——+————+———+———+——–+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+——-+——–+———-+——+————+———+———+——–+
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
+——-+——–+———-+——+————+———+———+——–+
两张不相干的表中的数据拼接在一起显示?
select ename from emp
union
select dname from dept;
mysql> select ename from emp union select dname from dept;
+————+
| ename |
+————+
| SMITH |
| ALLEN |
| WARD |
| JONES |
| MARTIN |
| BLAKE |
| CLARK |
| SCOTT |
| KING |
| TURNER |
| ADAMS |
| JAMES |
| FORD |
| MILLER |
| ACCOUNTING |
| RESEARCH |
| SALES |
| OPERATIONS |
+————+
Limit(重点中的重点)
特点:以后分页查询全靠它
Limit是mysql特有的,其他数据库中没有,不通用(oracle有一个相同的机制,叫做rownum).
limit取结果几种的部分数据,这时它的作用。
语法机制:
limit startIndex, length
startIndex表示起始位置
length表示取几个
案例:取出工资前五名的员工(思路:降序取前5个)
mysql> select ename,sal from emp order by sal desc limit 0,5;
+——-+———+
| ename | sal |
+——-+———+
| KING | 5000.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+——-+———+
5 rows in set (0.00 sec)mysql> select ename,sal from emp order by sal desc limit 5;
+——-+———+
| ename | sal |
+——-+———+
| KING | 5000.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+——-+———+
limit是sql语句最后执行的一个环节:
select 5
from 1
where 2
group by 3
having 4
order by 6
limit 7
案例:找出工资排名在第4到第9名的员工?
select ename,sal from emp order by sal desc limit 3,6;
+——–+———+
| ename | sal |
+——–+———+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
通用的标准分页sql?
每页显示3条记录:
第一页: 0, 3
第二页: 3, 3
第三页: 6, 3
每页显示pagesize条记录:
第pageNo页: pageSize*(pageNO-1), pagesize
pageSize是什么?是每页显示多少条记录
pageNo是什么?显示第几页
1 | java代码{ |