Mysql学习笔记第三章—复杂的查询语句
复杂的查询语句
1.关于查询结果集的去重
- 去重方法:在查询字段前加distinct
#distinct只能出现在所有字段的最前方
mysql> select distinct job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+
#distinct出现在最前方表示所有字段联合起来去重
mysql> select distinct ename,job from emp;
+--------+-----------+
| ename | job |
+--------+-----------+
| SMITH | CLERK |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| SCOTT | ANALYST |
| KING | PRESIDENT |
| TURNER | SALESMAN |
| ADAMS | CLERK |
| JAMES | CLERK |
| FORD | ANALYST |
| MILLER | CLERK |
+--------+-----------+
#统计job字段中的数量
mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
| 5 |
+---------------------+
2.连接查询
-
在实际开发中,大部分情况不是从单标查询,而是多张表联合查询取出最终结果。
-
根据表的连接方式对连接查询分类:
内连接:等值连接、非等值连接、自连接
外连接:左(外)连接、右(外)连接
全连接
-
笛卡尔积(乘积)现象:两张表进行连接查询没有任何条件限制时,最终查询结果为两表记录条数的乘积。
#这种语句会发生笛卡尔积现象
mysql> select ename,dname from emp,dept;
#关于表的别名语句
mysql>select e.ename,d.dname from emp e,dept d;
2.1内连接
-
内连接—等值连接:条件是等量关系。
常用语法:……A join B on 连接条件 where ……
避免笛卡尔积现象:加条件进行过滤。
#SQL92语法,一般少用。
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 |
+--------+------------+
#SQL99语法(常用): ……A inner join B on 连接条件 where ……
#其中inner可以省略
mysql> select e.ename,d.dname from emp e join dept d on 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 |
+--------+------------+
- 内连接—非等值连接:连接条件中的关系是非等量关系。
#工资名称表
mysql> select ename,sal from emp;
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| 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 |
+--------+---------+
#工资等级表
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
#要求查询每个人的工资等级
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 |
+--------+---------+-------+
- 自连接:一张表看为两张表。
#一张表中的员工和对应的上级领导编号
mysql> select empno,ename,mgr from emp;
+-------+--------+------+
| empno | ename | mgr |
+-------+--------+------+
| 7369 | SMITH | 7902 |
| 7499 | ALLEN | 7698 |
| 7521 | WARD | 7698 |
| 7566 | JONES | 7839 |
| 7654 | MARTIN | 7698 |
| 7698 | BLAKE | 7839 |
| 7782 | CLARK | 7839 |
| 7788 | SCOTT | 7566 |
| 7839 | KING | NULL |
| 7844 | TURNER | 7698 |
| 7876 | ADAMS | 7788 |
| 7900 | JAMES | 7698 |
| 7902 | FORD | 7566 |
| 7934 | MILLER | 7782 |
+-------+--------+------+
#要求:显示员工名和对应的领导名
mysql> select a.empno,a.ename as '员工名',b.ename as '领导名' from emp a join emp b on a.mgr = b.empno;
+-------+-----------+-----------+
| empno | 员工名 | 领导名 |
+-------+-----------+-----------+
| 7369 | SMITH | FORD |
| 7499 | ALLEN | BLAKE |
| 7521 | WARD | BLAKE |
| 7566 | JONES | KING |
| 7654 | MARTIN | BLAKE |
| 7698 | BLAKE | KING |
| 7782 | CLARK | KING |
| 7788 | SCOTT | JONES |
| 7844 | TURNER | BLAKE |
| 7876 | ADAMS | SCOTT |
| 7900 | JAMES | BLAKE |
| 7902 | FORD | JONES |
| 7934 | MILLER | CLARK |
+-------+-----------+-----------+
2.2外连接
-
内连接和外连接的区别:
内连接:A和B两张表使用内连接时,A和B能够匹配上的记录查询出来。两张表没有主副之分,是平等的。
外连接:A和B两张表使用外连接,A和B中有一张是主表,一张是副表,主要查询主表中的数据,顺便查询副表。当副表中数据没有和主表中数据匹配上,副表模拟出NULL与之匹配。
-
外连接分类:
左连接:表示左边的表是主表
右连接:表示右边的表是主表
#一张表中的员工和对应的上级领导编号
mysql> select empno,ename,mgr from emp;
+-------+--------+------+
| empno | ename | mgr |
+-------+--------+------+
| 7369 | SMITH | 7902 |
| 7499 | ALLEN | 7698 |
| 7521 | WARD | 7698 |
| 7566 | JONES | 7839 |
| 7654 | MARTIN | 7698 |
| 7698 | BLAKE | 7839 |
| 7782 | CLARK | 7839 |
| 7788 | SCOTT | 7566 |
| 7839 | KING | NULL |
| 7844 | TURNER | 7698 |
| 7876 | ADAMS | 7788 |
| 7900 | JAMES | 7698 |
| 7902 | FORD | 7566 |
| 7934 | MILLER | 7782 |
+-------+--------+------+
#左连接 left outer join
#outer可以省略
mysql> select a.empno,a.ename as'员工名',b.ename as '领导名' from emp a left join emp b on a.mgr = b.empno;
+-------+-----------+-----------+
| empno | 员工名 | 领导名 |
+-------+-----------+-----------+
| 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 |
+-------+-----------+-----------+
#右连接right outer join
#outer可以省略
mysql> select a.empno,a.ename as'员工名',b.ename as '领导名' from emp b right join emp a on a.mgr = b.empno;
+-------+-----------+-----------+
| empno | 员工名 | 领导名 |
+-------+-----------+-----------+
| 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 |
+-------+-----------+-----------+
#找出哪个部门没有员工
mysql> select d.deptno,d.dname from emp e right join dept d on e.deptno = d.deptno where e.empno is null;
+--------+------------+
| deptno | dname |
+--------+------------+
| 40 | OPERATIONS |
+--------+------------+
2.3三张表连接查询
- 需求:找出每个员工的部门名称以及工资等级。
#emp员工表
mysql> select empno,ename,deptno,sal from emp;
+-------+--------+--------+---------+
| empno | ename | deptno | sal |
+-------+--------+--------+---------+
| 7369 | SMITH | 20 | 800.00 |
| 7499 | ALLEN | 30 | 1600.00 |
| 7521 | WARD | 30 | 1250.00 |
| 7566 | JONES | 20 | 2975.00 |
| 7654 | MARTIN | 30 | 1250.00 |
| 7698 | BLAKE | 30 | 2850.00 |
| 7782 | CLARK | 10 | 2450.00 |
| 7788 | SCOTT | 20 | 3000.00 |
| 7839 | KING | 10 | 5000.00 |
| 7844 | TURNER | 30 | 1500.00 |
| 7876 | ADAMS | 20 | 1100.00 |
| 7900 | JAMES | 30 | 950.00 |
| 7902 | FORD | 20 | 3000.00 |
| 7934 | MILLER | 10 | 1300.00 |
+-------+--------+--------+---------+
#dept部门表
mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
4 rows in set (0.00 sec)
#salgrade工资等级表
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
#找出每个员工的部门名称以及工资等级。
mysql> 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 s.losal and s.hisal;
+--------+------------+-------+
| ename | dname | grade |
+--------+------------+-------+
| SMITH | RESEARCH | 1 |
| ALLEN | SALES | 3 |
| WARD | SALES | 2 |
| JONES | RESEARCH | 4 |
| MARTIN | SALES | 2 |
| BLAKE | SALES | 4 |
| CLARK | ACCOUNTING | 4 |
| SCOTT | RESEARCH | 4 |
| KING | ACCOUNTING | 5 |
| TURNER | SALES | 3 |
| ADAMS | RESEARCH | 1 |
| JAMES | SALES | 1 |
| FORD | RESEARCH | 4 |
| MILLER | ACCOUNTING | 2 |
+--------+------------+-------+
#找出每个员工的部门名称以及工资等级以及上级领导。
mysql> select e.ename,d.dname,s.grade,eb.ename as 'leader' from emp e join dept d join salgrade s on e.deptno = d.deptno and e.sal between s.losal and s.hisal left join emp eb on e.mgr = eb.empno;
+--------+------------+-------+--------+
| ename | dname | grade | leader |
+--------+------------+-------+--------+
| SMITH | RESEARCH | 1 | FORD |
| ALLEN | SALES | 3 | BLAKE |
| WARD | SALES | 2 | BLAKE |
| JONES | RESEARCH | 4 | KING |
| MARTIN | SALES | 2 | BLAKE |
| BLAKE | SALES | 4 | KING |
| CLARK | ACCOUNTING | 4 | KING |
| SCOTT | RESEARCH | 4 | JONES |
| KING | ACCOUNTING | 5 | NULL |
| TURNER | SALES | 3 | BLAKE |
| ADAMS | RESEARCH | 1 | SCOTT |
| JAMES | SALES | 1 | BLAKE |
| FORD | RESEARCH | 4 | JONES |
| MILLER | ACCOUNTING | 2 | CLARK |
+--------+------------+-------+--------+
3.子查询
-
select语句中嵌套select语句,被嵌套的select句子是子查询
select …(select). from …(select) where …(select)…
#找出高于平均薪资的员工信息
#注意where后面不能使用分组函数
#where后面嵌套子查询
mysql> select empno,ename,job,hiredate,sal,deptno from emp where sal>(select avg(sal) from emp);
+-------+-------+-----------+------------+---------+--------+
| empno | ename | job | hiredate | sal | deptno |
+-------+-------+-----------+------------+---------+--------+
| 7566 | JONES | MANAGER | 1981-04-02 | 2975.00 | 20 |
| 7698 | BLAKE | MANAGER | 1981-05-01 | 2850.00 | 30 |
| 7782 | CLARK | MANAGER | 1981-06-09 | 2450.00 | 10 |
| 7788 | SCOTT | ANALYST | 1987-04-19 | 3000.00 | 20 |
| 7839 | KING | PRESIDENT | 1981-11-17 | 5000.00 | 10 |
| 7902 | FORD | ANALYST | 1981-12-03 | 3000.00 | 20 |
+-------+-------+-----------+------------+---------+--------+
#from后面嵌套子查询
#找出每个部门平均薪水的薪资等级
mysql> select t.*,s.grade,d.dname from (select deptno,avg(sal) as 'avgsal' from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal left join dept d on t.deptno = d.deptno;
+--------+-------------+-------+------------+
| deptno | avgsal | grade | dname |
+--------+-------------+-------+------------+
| 20 | 2175.000000 | 4 | RESEARCH |
| 30 | 1566.666667 | 3 | SALES |
| 10 | 2916.666667 | 4 | ACCOUNTING |
+--------+-------------+-------+------------+
#在select后面嵌套子查询
#找出每个员工所在的部门名称,要求显示员工名和部门名
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 |
+--------+------------+
4.集相加
- union:可以将查询结果集相加。
#找出job中是SALESMAN和MANAGER的ename
#第一种方式
mysql> select ename,job from emp where job='MANAGER' or job='SALESMAN';
#第二种方式
mysql> select ename,job from emp where job in('MANAGER','SALESMAN');
#第三种方式,union方式
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 |
+--------+----------+
5.limit
-
limit是mysql特有的,其他数据库没有。(Oracle中有一个相同的机制,叫做rownum)
-
limit取结果集中的部分数据,可以用来分页查询。
语法机制:limit startIndex,length
startIndex表示起始位置,length表示取个数。
#取出工资前5名的员工(思路降序取前5个)
mysql> 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 |
+-------+---------+
#找出工资在第4到第9名员工(下标从0开始,第4名是3)
mysql> 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 |
+--------+---------+
-
小结:
select … from … where … group by …having … order by … limit…;
学习视频:动力节点MySQL基础入门到精通
原文地址:https://blog.csdn.net/weixin_46016581/article/details/135893156
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!