MySQL的复合查询
本文最后更新于 362 天前,如有失效请评论区留言。

 MySQL一切皆表!

基本查询(案例)

  • 工资高于高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J

    # 方法1
    mysql> select * from emp where (sal>500 or job='MANAGER') and (ename like 'J%');
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    | 007900 | JAMES | CLERK   | 7698 | 1981-12-03 00:00:00 |  950.00 | NULL |     30 |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    2 rows in set (0.00 sec)
    
    # 方法2
    mysql> select * from emp where (sal>500 or job='MANAGER') and (substring(ename,1,1) = 'J');
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    | 007900 | JAMES | CLERK   | 7698 | 1981-12-03 00:00:00 |  950.00 | NULL |     30 |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    2 rows in set (0.01 sec)
  • 按照部门号升序而雇员的工资降序排序

    mysql> select * from emp order by deptno asc, sal desc;
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    14 rows in set (0.00 sec)
  • 使用年薪进行降序排序

    mysql> select * , sal*12+ifnull(comm, 0) as 年薪 from emp order by 年薪 desc;
    +--------+--------+-----------+------+---------------------+---------+---------+--------+----------+
    | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno | 年薪     |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+----------+
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 | 60000.00 |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 | 36000.00 |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 | 36000.00 |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 | 35700.00 |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 | 34200.00 |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 | 29400.00 |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 | 19500.00 |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 | 18000.00 |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 | 16400.00 |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 | 15600.00 |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 | 15500.00 |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 | 13200.00 |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 | 11400.00 |
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |  9600.00 |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+----------+
    14 rows in set (0.00 sec)

    年薪是sal*12+comm,而在设计表时候,comm是default null的,没有设置default为0,null是无法参与运算的(与null运算的结果是null)。也就是说有的人没有奖金,有的人有奖金,但是不能直接加上comm,应该先用ifnull函数将null转换成0,才可以运算!

    这是符合现实的,因为有的岗位没有奖金(比如上表中很多人comm为null),有的岗位有奖金(比如上表中TURNER这个人的奖金是0,这个岗位是有奖金的,只是他得了0罢了)。

    下面附上建表的语句:

    mysql> show create table emp \G
    *************************** 1. row ***************************
        Table: emp
    Create Table: CREATE TABLE emp (
    empno int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
    ename varchar(10) DEFAULT NULL COMMENT '雇员姓名',
    job varchar(9) DEFAULT NULL COMMENT '雇员职位',
    mgr int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
    hiredate datetime DEFAULT NULL COMMENT '雇佣时间',
    sal decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
    comm decimal(7,2) DEFAULT NULL COMMENT '奖金',
    deptno int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
    1 row in set (0.00 sec)
  • 显示工资最高的员工的名字和工作岗位

    mysql> select ename, job from emp where sal=(select max(sal) from emp);
    +-------+-----------+
    | ename | job       |
    +-------+-----------+
    | KING  | PRESIDENT |
    +-------+-----------+
    1 row in set (0.00 sec)

    sql中是允许一条select中嵌套select的,优先执行内部的select。

  • 显示工资高于平均工资的员工信息

    mysql> select * from emp where sal>(select avg(sal) from emp);
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    | empno  | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    | 007566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    | 007698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
    | 007782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
    | 007788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
    | 007839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
    | 007902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    6 rows in set (0.00 sec)
  • 显示每个部门的平均工资和最高工资

    mysql> select deptno, format(max(sal),2) 最高工资, format(avg(sal),2) 平均工资 from emp group by deptno;
    +--------+--------------+--------------+
    | deptno | 最高工资     | 平均工资     |
    +--------+--------------+--------------+
    |     20 | 3,000.00     | 2,175.00     |
    |     30 | 2,850.00     | 1,566.67     |
    |     10 | 5,000.00     | 2,916.67     |
    +--------+--------------+--------------+
    3 rows in set (0.00 sec)
  • 显示平均工资低于2000的部门号,和它的平均工资

    mysql> select deptno, avg(sal) 平均工资 from emp group by deptno having 平均工资<=2000;
    +--------+--------------+
    | deptno | 平均工资     |
    +--------+--------------+
    |     30 |  1566.666667 |
    +--------+--------------+
    1 row in set (0.00 sec)
  • 显示每种岗位的雇员总数和平均工资

    mysql> select job, count(*) 人数, format(avg(sal),2) 平均工资 from emp group by job;
    +-----------+--------+--------------+
    | job       | 人数   | 平均工资     |
    +-----------+--------+--------------+
    | CLERK     |      4 | 1,037.50     |
    | SALESMAN  |      4 | 1,400.00     |
    | MANAGER   |      3 | 2,758.33     |
    | ANALYST   |      2 | 3,000.00     |
    | PRESIDENT |      1 | 5,000.00     |
    +-----------+--------+--------------+
    5 rows in set (0.01 sec)

多表查询(不同表)

  • 显示雇员名、雇员工资以及所在部门的名字当select * from emp, dept;的时候,得到的结果是将两张表拼接在一起。也就是emp表的每一行都与dept的每一行结合,这个结果就是笛卡尔积!如下示例:

    mysql> select * from emp;
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+
    14 rows in set (0.00 sec)
    
    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)
    
    mysql> select * from emp, dept;
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno | deptno | dname      | loc      |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |     40 | OPERATIONS | BOSTON   |
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |     30 | SALES      | CHICAGO  |
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |     10 | ACCOUNTING | NEW YORK |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |     40 | OPERATIONS | BOSTON   |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |     20 | RESEARCH   | DALLAS   |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |     40 | OPERATIONS | BOSTON   |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |     20 | RESEARCH   | DALLAS   |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |     40 | OPERATIONS | BOSTON   |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |     30 | SALES      | CHICAGO  |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |     10 | ACCOUNTING | NEW YORK |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |     40 | OPERATIONS | BOSTON   |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |     20 | RESEARCH   | DALLAS   |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |     40 | OPERATIONS | BOSTON   |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |     20 | RESEARCH   | DALLAS   |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |     40 | OPERATIONS | BOSTON   |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |     30 | SALES      | CHICAGO  |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |     20 | RESEARCH   | DALLAS   |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |     40 | OPERATIONS | BOSTON   |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |     30 | SALES      | CHICAGO  |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |     10 | ACCOUNTING | NEW YORK |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |     40 | OPERATIONS | BOSTON   |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |     30 | SALES      | CHICAGO  |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |     20 | RESEARCH   | DALLAS   |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |     40 | OPERATIONS | BOSTON   |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |     20 | RESEARCH   | DALLAS   |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |     40 | OPERATIONS | BOSTON   |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |     30 | SALES      | CHICAGO  |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |     10 | ACCOUNTING | NEW YORK |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |     40 | OPERATIONS | BOSTON   |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |     20 | RESEARCH   | DALLAS   |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |     10 | ACCOUNTING | NEW YORK |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |     40 | OPERATIONS | BOSTON   |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |     30 | SALES      | CHICAGO  |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |     10 | ACCOUNTING | NEW YORK |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |     40 | OPERATIONS | BOSTON   |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |     30 | SALES      | CHICAGO  |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |     20 | RESEARCH   | DALLAS   |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    56 rows in set (0.00 sec)

    但是这样得到的很多的内容是无意义的,这时候就需要手动筛选出有意义的内容了,就如这里,选出deptno相同的保留,其余排除:

    mysql> select * from emp, dept where emp.deptno=dept.deptno;
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno | deptno | dname      | loc      |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
    | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |     30 | SALES      | CHICAGO  |
    | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
    | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
    | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
    +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
    14 rows in set (0.00 sec)
    
    mysql> select ename, sal, dname from emp, dept where emp.deptno=dept.deptno;
    +--------+---------+------------+
    | ename  | sal     | dname      |
    +--------+---------+------------+
    | SMITH  |  800.00 | RESEARCH   |
    | ALLEN  | 1600.00 | SALES      |
    | WARD   | 1250.00 | SALES      |
    | JONES  | 2975.00 | RESEARCH   |
    | MARTIN | 1250.00 | SALES      |
    | BLAKE  | 2850.00 | SALES      |
    | CLARK  | 2450.00 | ACCOUNTING |
    | SCOTT  | 3000.00 | RESEARCH   |
    | KING   | 5000.00 | ACCOUNTING |
    | TURNER | 1500.00 | SALES      |
    | ADAMS  | 1100.00 | RESEARCH   |
    | JAMES  |  950.00 | SALES      |
    | FORD   | 3000.00 | RESEARCH   |
    | MILLER | 1300.00 | ACCOUNTING |
    +--------+---------+------------+
    14 rows in set (0.00 sec)
    
  • 显示部门号为10的部门名、员工名和工资

    mysql> select dname, ename,sal from emp, dept where emp.deptno=dept.deptno and emp.deptno=10;
    +------------+--------+---------+
    | dname      | ename  | sal     |
    +------------+--------+---------+
    | ACCOUNTING | CLARK  | 2450.00 |
    | ACCOUNTING | KING   | 5000.00 |
    | ACCOUNTING | MILLER | 1300.00 |
    +------------+--------+---------+
    3 rows in set (0.00 sec)
  • 显示各个员工的姓名、工资、工资级别

    mysql> select ename, sal, grade, losal, hisal from emp, salgrade where sal between losal and hisal;
    +--------+---------+-------+-------+-------+
    | ename  | sal     | grade | losal | hisal |
    +--------+---------+-------+-------+-------+
    | SMITH  |  800.00 |     1 |   700 |  1200 |
    | ALLEN  | 1600.00 |     3 |  1401 |  2000 |
    | WARD   | 1250.00 |     2 |  1201 |  1400 |
    | JONES  | 2975.00 |     4 |  2001 |  3000 |
    | MARTIN | 1250.00 |     2 |  1201 |  1400 |
    | BLAKE  | 2850.00 |     4 |  2001 |  3000 |
    | CLARK  | 2450.00 |     4 |  2001 |  3000 |
    | SCOTT  | 3000.00 |     4 |  2001 |  3000 |
    | KING   | 5000.00 |     5 |  3001 |  9999 |
    | TURNER | 1500.00 |     3 |  1401 |  2000 |
    | ADAMS  | 1100.00 |     1 |   700 |  1200 |
    | JAMES  |  950.00 |     1 |   700 |  1200 |
    | FORD   | 3000.00 |     4 |  2001 |  3000 |
    | MILLER | 1300.00 |     2 |  1201 |  1400 |
    +--------+---------+-------+-------+-------+
    14 rows in set (0.00 sec)

自连接(相同的表)

刚刚的多表查询是在不同的表之间进行的,下面来看看同一张表进行自连接(笛卡尔积查询):

mysql> select * from salgrade as t1, salgrade as t2;
+-------+-------+-------+-------+-------+-------+
| grade | losal | hisal | grade | losal | hisal |
+-------+-------+-------+-------+-------+-------+
|     5 |  3001 |  9999 |     1 |   700 |  1200 |
|     4 |  2001 |  3000 |     1 |   700 |  1200 |
|     3 |  1401 |  2000 |     1 |   700 |  1200 |
|     2 |  1201 |  1400 |     1 |   700 |  1200 |
|     1 |   700 |  1200 |     1 |   700 |  1200 |
|     5 |  3001 |  9999 |     2 |  1201 |  1400 |
|     4 |  2001 |  3000 |     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |     2 |  1201 |  1400 |
|     2 |  1201 |  1400 |     2 |  1201 |  1400 |
|     1 |   700 |  1200 |     2 |  1201 |  1400 |
|     5 |  3001 |  9999 |     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |     3 |  1401 |  2000 |
|     3 |  1401 |  2000 |     3 |  1401 |  2000 |
|     2 |  1201 |  1400 |     3 |  1401 |  2000 |
|     1 |   700 |  1200 |     3 |  1401 |  2000 |
|     5 |  3001 |  9999 |     4 |  2001 |  3000 |
|     4 |  2001 |  3000 |     4 |  2001 |  3000 |
|     3 |  1401 |  2000 |     4 |  2001 |  3000 |
|     2 |  1201 |  1400 |     4 |  2001 |  3000 |
|     1 |   700 |  1200 |     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |     5 |  3001 |  9999 |
|     4 |  2001 |  3000 |     5 |  3001 |  9999 |
|     3 |  1401 |  2000 |     5 |  3001 |  9999 |
|     2 |  1201 |  1400 |     5 |  3001 |  9999 |
|     1 |   700 |  1200 |     5 |  3001 |  9999 |
+-------+-------+-------+-------+-------+-------+
25 rows in set (0.00 sec)

因为同一张表,名字是相同的,所以必须先重命名才可以进行自连接!

  • 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号)

    # 方法1:子查询
    mysql> select ename, empno from emp where empno=(select mgr from emp where ename='FORD');
    +-------+--------+
    | ename | empno  |
    +-------+--------+
    | JONES | 007566 |
    +-------+--------+
    1 row in set (0.00 sec)
    
    # 方法2:自连接
    mysql> select e2.ename, e2.empno from emp e1, emp e2 where e1.ename='FORD' and e1.mgr=e2.empno;
    +-------+--------+
    | ename | empno  |
    +-------+--------+
    | JONES | 007566 |
    +-------+--------+
    1 row in set (0.00 sec)

子查询

所谓子查询,就是嵌套在其他的sql语句中的select语句。

单行子查询

返回一行记录的子查询。

  • 显示SMITH同一部门的员工

    mysql> select * from emp where deptno=(select deptno from emp where ename='SMITH');
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    | 007369 | SMITH | CLERK   | 7902 | 1980-12-17 00:00:00 |  800.00 | NULL |     20 |
    | 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    | 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
    | 007876 | ADAMS | CLERK   | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL |     20 |
    | 007902 | FORD  | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
    +--------+-------+---------+------+---------------------+---------+------+--------+
    5 rows in set (0.00 sec)

多行子查询

返回多行记录的子查询

  • 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自
    己的。

    关键字in:查询在in范围内的内容。

    mysql> select ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10) and deptno!=10;
    +-------+---------+---------+--------+
    | ename | job     | sal     | deptno |
    +-------+---------+---------+--------+
    | SMITH | CLERK   |  800.00 |     20 |
    | JONES | MANAGER | 2975.00 |     20 |
    | BLAKE | MANAGER | 2850.00 |     30 |
    | ADAMS | CLERK   | 1100.00 |     20 |
    | JAMES | CLERK   |  950.00 |     30 |
    +-------+---------+---------+--------+
    5 rows in set (0.00 sec)
    
    # 如果再进一步:在此基础上,再把部门的名称也显示出来:
    mysql> select ename, job, sal, dept.deptno, dname from (select ename,job,sal,deptno from emp where job in (select distinct job from emp where depttno=10) and deptno!=10) as tmp, dept where dept.deptno=tmp.deptno;
    +-------+---------+---------+--------+----------+
    | ename | job     | sal     | deptno | dname    |
    +-------+---------+---------+--------+----------+
    | ADAMS | CLERK   | 1100.00 |     20 | RESEARCH |
    | JONES | MANAGER | 2975.00 |     20 | RESEARCH |
    | SMITH | CLERK   |  800.00 |     20 | RESEARCH |
    | JAMES | CLERK   |  950.00 |     30 | SALES    |
    | BLAKE | MANAGER | 2850.00 |     30 | SALES    |
    +-------+---------+---------+--------+----------+
    5 rows in set (0.00 sec)
  • 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
    关键字all:表示括号里所有的内容(见方法2)

    # 方法1 比最大的还大
    mysql> select ename, sal, deptno from emp where sal>(select max(sal) from emp where deptno=30);
    +-------+---------+--------+
    | ename | sal     | deptno |
    +-------+---------+--------+
    | JONES | 2975.00 |     20 |
    | SCOTT | 3000.00 |     20 |
    | KING  | 5000.00 |     10 |
    | FORD  | 3000.00 |     20 |
    +-------+---------+--------+
    4 rows in set (0.00 sec)
    
    # 方法2 比所有的都大
    mysql> select ename, sal, deptno from emp where sal > all(select distinct sal from emp where deptno=30);
    +-------+---------+--------+
    | ename | sal     | deptno |
    +-------+---------+--------+
    | JONES | 2975.00 |     20 |
    | SCOTT | 3000.00 |     20 |
    | KING  | 5000.00 |     10 |
    | FORD  | 3000.00 |     20 |
    +-------+---------+--------+
    4 rows in set (0.01 sec)

  • 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门
    的员工)
    关键字any:表示括号里的任意一个内容

    mysql> select ename, sal, deptno from emp where sal > any(select distinct sal from emp where deptno=30);
    +--------+---------+--------+
    | ename  | sal     | deptno |
    +--------+---------+--------+
    | ALLEN  | 1600.00 |     30 |
    | WARD   | 1250.00 |     30 |
    | JONES  | 2975.00 |     20 |
    | MARTIN | 1250.00 |     30 |
    | BLAKE  | 2850.00 |     30 |
    | CLARK  | 2450.00 |     10 |
    | SCOTT  | 3000.00 |     20 |
    | KING   | 5000.00 |     10 |
    | TURNER | 1500.00 |     30 |
    | ADAMS  | 1100.00 |     20 |
    | FORD   | 3000.00 |     20 |
    | MILLER | 1300.00 |     10 |
    +--------+---------+--------+
    12 rows in set (0.00 sec)

多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句。

  • 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

    mysql> select * from emp where (deptno,job) in (select deptno, job from emp where ename='SMITH') and ename <> 'SMITH';
    +--------+-------+-------+------+---------------------+---------+------+--------+
    | empno  | ename | job   | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+-------+------+---------------------+---------+------+--------+
    | 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL |     20 |
    +--------+-------+-------+------+---------------------+---------+------+--------+
    1 row in set (0.00 sec)

    这里的in也可以用=

在from子句中使用子查询

上面涉及到的所有子查询都是在where中的。实际上可以把任意一个查询的结果当成一个表来看待,下面来看from中的子查询。

  • 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

    mysql> select ename, emp.deptno,sal,AVG from emp, (select deptno, avg(sal) AVG from emp group by deptno) as tmp where emp.deptno=tmp.deptno and sall>AVG;
    +-------+--------+---------+-------------+
    | ename | deptno | sal     | AVG         |
    +-------+--------+---------+-------------+
    | ALLEN |     30 | 1600.00 | 1566.666667 |
    | JONES |     20 | 2975.00 | 2175.000000 |
    | BLAKE |     30 | 2850.00 | 1566.666667 |
    | SCOTT |     20 | 3000.00 | 2175.000000 |
    | KING  |     10 | 5000.00 | 2916.666667 |
    | FORD  |     20 | 3000.00 | 2175.000000 |
    +-------+--------+---------+-------------+
    6 rows in set (0.00 sec)
    
    # 拓展:在此基础上,再显示这些员工的办公地点
    mysql> select t1.ename, dept.loc, t1.deptno from dept,(select ename, emp.deptno,sal,AVG from emp, (select deptno, avg(sal) AVG from emp group by deeptno) as tmp where emp.deptno=tmp.deptno and sal>AVG) as t1 where t1.deptno=dept.deptno;
    +-------+----------+--------+
    | ename | loc      | deptno |
    +-------+----------+--------+
    | ALLEN | CHICAGO  |     30 |
    | JONES | DALLAS   |     20 |
    | BLAKE | CHICAGO  |     30 |
    | SCOTT | DALLAS   |     20 |
    | KING  | NEW YORK |     10 |
    | FORD  | DALLAS   |     20 |
    +-------+----------+--------+
    6 rows in set (0.00 sec)
  • 查找每个部门工资最高的人的姓名、工资、部门、最高工资

    mysql> select ename, sal, t1.deptno, 最高工资 from emp as t1, (select deptno, max(sal) 最高工资 from emp group by deptno) as t2 where t1.deptno=t2..deptno and t1.sal=t2.最高工资;
    +-------+---------+--------+--------------+
    | ename | sal     | deptno | 最高工资     |
    +-------+---------+--------+--------------+
    | BLAKE | 2850.00 |     30 |      2850.00 |
    | SCOTT | 3000.00 |     20 |      3000.00 |
    | KING  | 5000.00 |     10 |      5000.00 |
    | FORD  | 3000.00 |     20 |      3000.00 |
    +-------+---------+--------+--------------+
    4 rows in set (0.00 sec)
  • 显示每个部门的信息(部门名、编号、地址、人员数量)

    # 方法1:多表笛卡尔积+子查询
    mysql> select dname, t1.deptno, loc, dept_num from dept t1, (select deptno, count(*) dept_num from emp group by deptno) t2 where t1.deptno=t2.deptn
    no;
    +------------+--------+----------+----------+
    | dname      | deptno | loc      | dept_num |
    +------------+--------+----------+----------+
    | ACCOUNTING |     10 | NEW YORK |        3 |
    | RESEARCH   |     20 | DALLAS   |        5 |
    | SALES      |     30 | CHICAGO  |        6 |
    +------------+--------+----------+----------+
    3 rows in set (0.00 sec)
    
    # 方法2:简单粗暴多表查询
    mysql> select dept.dname, dept.deptno, dept.loc, count(*) '部门人数' from emp, dept where emp.deptno=dept.deptno group by dept.deptno,dept.dname,dEept.loc;
    +------------+--------+----------+--------------+
    | dname      | deptno | loc      | 部门人数     |
    +------------+--------+----------+--------------+
    | RESEARCH   |     20 | DALLAS   |            5 |
    | SALES      |     30 | CHICAGO  |            6 |
    | ACCOUNTING |     10 | NEW YORK |            3 |
    +------------+--------+----------+--------------+
    3 rows in set (0.00 sec)

    合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all(不是笛卡尔积,笛卡尔积是相乘穷举,合并查询是简单的全部罗列出来)

union

取得两个结果集的并集。

  • 将工资大于2500或者职位是MANAGER的人找出来(去重)

    # 方法1:简单方法
    mysql> select * from emp where sal > 2500 or job = 'MANAGER';
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    | empno  | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    | 007566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    | 007698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
    | 007782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
    | 007788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
    | 007839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
    | 007902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
    +--------+-------+-----------+------+---------------------+---------+------+--------+
    6 rows in set (0.01 sec)
    
    # 方法2:用union
    mysql> select * from emp where sal > 2500 union select * from emp where job='MANAGER';
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    | empno | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    |  7566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    |  7698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
    |  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
    |  7839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
    |  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
    |  7782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    6 rows in set (0.00 sec)

union all

取得两个结果集的并集。

  • 将工资大于2500或者职位是MANAGER的人找出来(不去重)

    mysql> select * from emp where sal > 2500 union all select * from emp where job='MANAGER';
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    | empno | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    |  7566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
    |  7698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
    |  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
    |  7839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
    |  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
    |  7782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
    +-------+-------+-----------+------+---------------------+---------+------+--------+
    6 rows in set (0.00 sec)

总结

 解决多表问题的本质:想办法把多表转化成单表,所以MySQL中所有的select问题都可以转化成单表问题。MySQL一切皆表!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇