MySQL查询

查询结果

关于查询结果集的去重?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
2
3
4
5
6
7
java代码{

​ int pageNo = 2; //
​ int page size = 10;
​ limit (pageNo - 1)*pagesize , pagesize

}

本文标题:MySQL查询

文章作者:孤桜懶契

发布时间:2020年10月05日 - 11:05:35

最后更新:2021年10月20日 - 13:10:02

原始链接:https://gylq.gitee.io/posts/11.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------