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基础入门到精通

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值