MySql | 数据查询语句(DQL)

文章目录

简单查询

查询单个字段

select <字段名> from <表名>
  • 查询部门名

    select dname from dept;
    
    mysql> select dname from dept;
    +------------+
    | dname      |
    +------------+
    | ACCOUNTING |
    | RESEARCH   |
    | SALES      |
    | OPERATIONS |
    +------------+
    4 rows in set (0.00 sec)
    

查询多个字段

select <字段名1>, <字段名2>, ..., <字段名n> from <表名>
// 输入的字段顺序就是之后展示的顺序
  • 查询部门编号和部门名

    select deptno, dname from dept;
    select dname, deptno from dept;
    
    mysql> select deptno, dname from dept;
    +--------+------------+
    | deptno | dname      |
    +--------+------------+
    |     10 | ACCOUNTING |
    |     20 | RESEARCH   |
    |     30 | SALES      |
    |     40 | OPERATIONS |
    +--------+------------+
    4 rows in set (0.00 sec)
    
    mysql> select dname, deptno from dept;
    +------------+--------+
    | dname      | deptno |
    +------------+--------+
    | ACCOUNTING |     10 |
    | RESEARCH   |     20 |
    | SALES      |     30 |
    | OPERATIONS |     40 |
    +------------+--------+
    4 rows in set (0.00 sec)
    

查询所有字段

select <字段名1>, <字段名2>, ..., <字段名n> from <表名>	// 输入所有的字段名
select * from <表名>		// 用*代替所有
// 后者会先将*解读为所有具体的字段再运行,效率更低;同时可读性更差,不推荐在实际开发中使用
// 但自己想要快速查看所有数据时可以使用
  • 查询dept表中所有数据

    select deptno, dname, loc from dept;	// 输入所有的字段名
    select * from dept;			// 用*代替所有
    
    mysql> select deptno, dname, loc 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 dept;
    +--------+------------+----------+
    | DEPTNO | DNAME      | LOC      |
    +--------+------------+----------+
    |     10 | ACCOUNTING | NEW YORK |
    |     20 | RESEARCH   | DALLAS   |
    |     30 | SALES      | CHICAGO  |
    |     40 | OPERATIONS | BOSTON   |
    +--------+------------+----------+
    4 rows in set (0.00 sec)
    

字段起别名

// 用as关键字
select <字段名> as <字段名别名> from <表名>
select <字段名1> as <字段1别名>, <字段名2> as <字段2别名>, ..., <字段名n> as <字段n别名> from <表名>

// as关键字也可以省略
select <字段名> <字段名别名> from <表名>
select <字段名1> <字段1别名>, <字段名2> <字段2别名>, ..., <字段名n> <字段n别名> from <表名>
  • 查询部门编号和部门名,并给部门名字段起别名

    注意:只是将显示的查询结果列名显示为deptname,原表列名还是叫:dname

    记住:select语句是永远都不会进行修改操作的。(因为只负责查询)

    select deptno, dname as deptname from dept;
    
    mysql> select deptno, dname as deptname from dept;
    +--------+------------+
    | deptno | deptname   |
    +--------+------------+
    |     10 | ACCOUNTING |
    |     20 | RESEARCH   |
    |     30 | SALES      |
    |     40 | OPERATIONS |
    +--------+------------+
    4 rows in set (0.00 sec)
    
  • 起的别名可以是中文

    select deptno 部门编号, dname 部门名 from dept;
    
    mysql> select deptno 部门编号, dname 部门名 from dept;
    +--------------+------------+
    | 部门编号     | 部门名     |
    +--------------+------------+
    |           10 | ACCOUNTING |
    |           20 | RESEARCH   |
    |           30 | SALES      |
    |           40 | OPERATIONS |
    +--------------+------------+
    4 rows in set (0.00 sec)
    
  • 起的别名中包含空格,需要用单引号括起来

    也可以使用双引号,但在SQL语言中,单引号表示字符串是标准,双引号是不标准的

    select deptno, dname 'dept name' from dept;
    
    mysql> select deptno, dname 'dept name' from dept;
    +--------+------------+
    | deptno | dept name  |
    +--------+------------+
    |     10 | ACCOUNTING |
    |     20 | RESEARCH   |
    |     30 | SALES      |
    |     40 | OPERATIONS |
    +--------+------------+
    4 rows in set (0.00 sec)
    

字段参与数学运算

select <字段名的数学运算式> from <表名>
select <字段名1的数学运算式>, <字段名2的数学运算式>, ..., <字段名n的数学运算式> from <表名>
  • 计算员工的年薪

    select ename, sal*12 from emp;
    select ename, sal*12 yearsal from emp;
    
    mysql> select ename, sal*12 from emp;
    +--------+----------+
    | ename  | sal*12   |
    +--------+----------+
    | SMITH  |  9600.00 |
    | ALLEN  | 19200.00 |
    | WARD   | 15000.00 |
    | JONES  | 35700.00 |
    | MARTIN | 15000.00 |
    | BLAKE  | 34200.00 |
    | CLARK  | 29400.00 |
    | SCOTT  | 36000.00 |
    | KING   | 60000.00 |
    | TURNER | 18000.00 |
    | ADAMS  | 13200.00 |
    | JAMES  | 11400.00 |
    | FORD   | 36000.00 |
    | MILLER | 15600.00 |
    +--------+----------+
    14 rows in set (0.00 sec)
    
    mysql> select ename, sal*12 yearsal from emp;
    +--------+----------+
    | ename  | yearsal  |
    +--------+----------+
    | SMITH  |  9600.00 |
    | ALLEN  | 19200.00 |
    | WARD   | 15000.00 |
    | JONES  | 35700.00 |
    | MARTIN | 15000.00 |
    | BLAKE  | 34200.00 |
    | CLARK  | 29400.00 |
    | SCOTT  | 36000.00 |
    | KING   | 60000.00 |
    | TURNER | 18000.00 |
    | ADAMS  | 13200.00 |
    | JAMES  | 11400.00 |
    | FORD   | 36000.00 |
    | MILLER | 15600.00 |
    +--------+----------+
    14 rows in set (0.00 sec)
    

条件查询

条件查询语法格式

select ... from ... where <条件表达式>

=:等于

  • 查询薪资等于800的员工信息

    select empno, ename from emp where sal=800;
    
    mysql> select empno, ename from emp where sal=800;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7369 | SMITH |
    +-------+-------+
    1 row in set (0.00 sec)
    
  • 查询史密斯的员工信息

    select empno, ename from emp where ename='smith';
    
    mysql> select empno, ename from emp where ename='smith';	// 字符串加单引号
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7369 | SMITH |
    +-------+-------+
    1 row in set (0.00 sec)
    

<>!=:不等于

  • 查询薪资不等于800的员工信息

    select empno, ename from emp where sal!=800;
    select empno, ename from emp where sal<>800;
    
    mysql> select empno, ename from emp where sal!=800;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7788 | SCOTT  |
    |  7839 | KING   |
    |  7844 | TURNER |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7902 | FORD   |
    |  7934 | MILLER |
    +-------+--------+
    13 rows in set (0.00 sec)
    
    mysql> select empno, ename from emp where sal<>800;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7788 | SCOTT  |
    |  7839 | KING   |
    |  7844 | TURNER |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7902 | FORD   |
    |  7934 | MILLER |
    +-------+--------+
    13 rows in set (0.00 sec)
    

<:小于

  • 查询薪资小于2000的员工信息

    select empno, ename from emp where sal<2000;
    
    mysql> select empno, ename from emp where sal<2000;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7369 | SMITH  |
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7654 | MARTIN |
    |  7844 | TURNER |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7934 | MILLER |
    +-------+--------+
    8 rows in set (0.00 sec)
    

<=:小于等于

  • 查询薪资小于等于3000的员工信息

    select empno, ename from emp where sal<=3000;
    
    mysql> select empno, ename from emp where sal<=3000;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7369 | SMITH  |
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7788 | SCOTT  |
    |  7844 | TURNER |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7902 | FORD   |
    |  7934 | MILLER |
    +-------+--------+
    13 rows in set (0.00 sec)
    

>:大于

  • 查询薪资大于3000的员工信息

    select empno, ename from emp where sal>3000;
    
    mysql> select empno, ename from emp where sal>3000;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7839 | KING  |
    +-------+-------+
    1 row in set (0.00 sec)
    

>=:大于等于

  • 查询薪资大于等于3000的员工信息

    select empno, ename from emp where sal>=3000;
    
    mysql> select empno, ename from emp where sal>=3000;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7788 | SCOTT |
    |  7839 | KING  |
    |  7902 | FORD  |
    +-------+-------+
    3 rows in set (0.00 sec)
    

between and>= and <=:两个值之间

between and 左小右大,且是闭区间

  • 查询薪资在2450到3000之间的员工信息

    select empno, ename from emp where sal>=2450 and sal<=3000;
    
    mysql> select empno, ename from emp where sal>=2450 and sal<=3000;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7566 | JONES |
    |  7698 | BLAKE |
    |  7782 | CLARK |
    |  7788 | SCOTT |
    |  7902 | FORD  |
    +-------+-------+
    5 rows in set (0.00 sec)
    
    mysql> select empno, ename from emp where sal between 2450 and 3000;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7566 | JONES |
    |  7698 | BLAKE |
    |  7782 | CLARK |
    |  7788 | SCOTT |
    |  7902 | FORD  |
    +-------+-------+
    5 rows in set (0.00 sec)
    

is null:为空,is not null:不为空

注意:在数据库当中nul1不能使用等号进行衡量。需要使用is null因为数据库中的nul1代表什么也没有,它不是一个值,所以不能使用等号衡量。

  • 查询哪些员工的津贴/补助为空

    select empno, ename from emp where comm is null;
    
    mysql> select empno, ename from emp where comm is null;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7369 | SMITH  |
    |  7566 | JONES  |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7788 | SCOTT  |
    |  7839 | KING   |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7902 | FORD   |
    |  7934 | MILLER |
    +-------+--------+
    10 rows in set (0.00 sec)
    
  • 查询哪些员工的津贴/补助不为空

    select empno, ename from emp where comm is not null;
    
    mysql> select empno, ename from emp where comm is not null;
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7654 | MARTIN |
    |  7844 | TURNER |
    +-------+--------+
    4 rows in set (0.00 sec)
    

and:且

  • 查询工作岗位是MANAGER并且工资大于2500的员工信息

    select empno, ename from emp where job='manager' and sal>2500;
    
    mysql> select empno, ename from emp where job='manager' and sal>2500;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7566 | JONES |
    |  7698 | BLAKE |
    +-------+-------+
    2 rows in set (0.00 sec)
    

or:或

  • 查询工作岗位是MANAGER和SALESMAN的员工

    select empno, ename from emp where job='manager' or job='salesman';
    
    mysql> select empno, ename from emp where job='manager' or job='salesman';
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7844 | TURNER |
    +-------+--------+
    7 rows in set (0.00 sec)
    

andor的优先级问题

and和or同时出现,and的优先级较高

  • 查询工资大于2500,并且部门编号为10或20部门的员工

    select empno, ename from emp where sal>2500 and (deptno=10 or deptno=20);
    
    mysql> select empno, ename from emp where sal>2500 and (deptno=10 or deptno=20);
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7566 | JONES |
    |  7788 | SCOTT |
    |  7839 | KING  |
    |  7902 | FORD  |
    +-------+-------+
    4 rows in set (0.00 sec)
    

in:在范围中,not in:不在范围中

in可以等价于多个or,注意in不是区间,in括号中是具体的值的罗列

  • 查询工作岗位是MANAGER和SALESMAN的员工信息

    select empno, ename from emp where job in('manager','salesman');
    
    mysql> select empno, ename from emp where job in('manager','salesman');
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7844 | TURNER |
    +-------+--------+
    7 rows in set (0.00 sec)
    
  • 查询工资不是800,3000,5000的员工信息

    select empno, ename from emp where sal not in(800, 3000, 5000);
    
    mysql> select empno, ename from emp where sal not in(800, 3000, 5000);
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7499 | ALLEN  |
    |  7521 | WARD   |
    |  7566 | JONES  |
    |  7654 | MARTIN |
    |  7698 | BLAKE  |
    |  7782 | CLARK  |
    |  7844 | TURNER |
    |  7876 | ADAMS  |
    |  7900 | JAMES  |
    |  7934 | MILLER |
    +-------+--------+
    10 rows in set (0.00 sec)
    

not:取非

主要用在is和in中,not isnot in

like:模糊查询

%百分号匹配任意多个字符,_下划线匹配任意单个字符(加反斜杠转义为普通字符)

  • 查询名字中含有o的员工信息

    select empno, ename from emp where ename like '%o%';
    
    mysql> select empno, ename from emp where ename like '%o%';
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7566 | JONES |
    |  7788 | SCOTT |
    |  7902 | FORD  |
    +-------+-------+
    3 rows in set (0.00 sec)
    
  • 查询名字中以t结尾的员工信息

    select empno, ename from emp where ename like '%t';
    
    mysql> select empno, ename from emp where ename like '%t';
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7788 | SCOTT |
    +-------+-------+
    1 row in set (0.00 sec)
    
  • 查询名字中以k开头的员工信息

    select empno, ename from emp where ename like 'k%';
    
    mysql> select empno, ename from emp where ename like 'k%';
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7839 | KING  |
    +-------+-------+
    1 row in set (0.00 sec)
    
  • 查询名字中第二个字母是a的员工信息

    select empno, ename from emp where ename like '_a%';
    
    mysql> select empno, ename from emp where ename like '_a%';
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7521 | WARD   |
    |  7654 | MARTIN |
    |  7900 | JAMES  |
    +-------+--------+
    3 rows in set (0.00 sec)
    
  • 查询名字中第三个字母是r的员工信息

    select empno, ename from emp where ename like '__r%';
    
    mysql> select empno, ename from emp where ename like '__r%';
    +-------+--------+
    | empno | ename  |
    +-------+--------+
    |  7521 | WARD   |
    |  7654 | MARTIN |
    |  7844 | TURNER |
    |  7902 | FORD   |
    +-------+--------+
    4 rows in set (0.00 sec)
    

排序

单个字段排序

select ... from ... where ... order by <字段名> (asc/desc)	
// 默认升序,加asc指定升序,加desc指定降序
  • 查询所有员工名字和薪资,并按薪资排序

    select ename, sal from emp order by sal;
    
    mysql> select ename, sal from emp order by sal;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | SCOTT  | 3000.00 |
    | FORD   | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
    14 rows in set (0.00 sec)
    
    mysql> select ename, sal from emp order by sal desc;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | KING   | 5000.00 |
    | SCOTT  | 3000.00 |
    | FORD   | 3000.00 |
    | JONES  | 2975.00 |
    | BLAKE  | 2850.00 |
    | CLARK  | 2450.00 |
    | ALLEN  | 1600.00 |
    | TURNER | 1500.00 |
    | MILLER | 1300.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    | ADAMS  | 1100.00 |
    | JAMES  |  950.00 |
    | SMITH  |  800.00 |
    +--------+---------+
    14 rows in set (0.00 sec)
    

多个字段排序

select ... from ... where ... order by <字段名1> (asc/desc), <字段名2> (asc/desc), ... , <字段名n> (asc/desc)
  • 查询所有员工名字和薪资,按薪资排序,薪资相同按名字升序

    select ename, sal from emp order by sal asc, ename asc;
    
    mysql> select ename, sal from emp order by sal asc, ename asc;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | MARTIN | 1250.00 |
    | WARD   | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | FORD   | 3000.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
    14 rows in set (0.00 sec)
    

根据字段的位置排序

select ... from ... where ... order by <字段位置> (asc/desc)		// 字段位置即列号
// 了解一下即可,不建议在开发中这样写,不具有健壮型
  • 查询所有员工名字和薪资,并按薪资排序

    select ename, sal from emp order by 2;
    
    mysql> select ename, sal from emp order by 2;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | SCOTT  | 3000.00 |
    | FORD   | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
    14 rows in set (0.00 sec)
    
  • 查询工资在1250到3000之间的员工信息,要求按照薪资降序排列

    select ename, sal from emp where sal between 1250 and 3000 order by sal desc;
    
    mysql> select ename, sal from emp where sal between 1250 and 3000 order by sal desc;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SCOTT  | 3000.00 |
    | FORD   | 3000.00 |
    | JONES  | 2975.00 |
    | BLAKE  | 2850.00 |
    | CLARK  | 2450.00 |
    | ALLEN  | 1600.00 |
    | TURNER | 1500.00 |
    | MILLER | 1300.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    +--------+---------+
    10 rows in set (0.00 sec)
    

单行处理函数

单行处理函数:输入一行,输出一行

单行处理函数又称数据处理函数

lower(字段名):转换小写

select lower(ename) from emp;
mysql> select lower(ename) from emp;
+--------------+
| lower(ename) |
+--------------+
| smith        |
| allen        |
| ward         |
| jones        |
| martin       |
| blake        |
| clark        |
| scott        |
| king         |
| turner       |
| adams        |
| james        |
| ford         |
| miller       |
+--------------+
14 rows in set (0.00 sec)

// 14个输入对应14个输出,这就是单行处理函数特点

upper(字段名):转换大写

select upper(ename) from emp;
mysql> select upper(ename) from emp;
+--------------+
| upper(ename) |
+--------------+
| SMITH        |
| ALLEN        |
| WARD         |
| JONES        |
| MARTIN       |
| BLAKE        |
| CLARK        |
| SCOTT        |
| KING         |
| TURNER       |
| ADAMS        |
| JAMES        |
| FORD         |
| MILLER       |
+--------------+
14 rows in set (0.00 sec)

substr(字段名, 起始下标, 截取长度):取子串

select substr(ename, 1, 1) from emp;
mysql> select substr(ename, 1, 1) from emp;
+---------------------+
| substr(ename, 1, 1) |
+---------------------+
| S                   |
| A                   |
| W                   |
| J                   |
| M                   |
| B                   |
| C                   |
| S                   |
| K                   |
| T                   |
| A                   |
| J                   |
| F                   |
| M                   |
+---------------------+
14 rows in set (0.00 sec)

查询姓名第一字母为A的员工信息

select ename from emp where ename like 'A%';		// 方法一:模糊查询
select ename from emp where substr(ename, 1, 1)='A';	// 方法二:用substr()函数
// 方法一:模糊查询
mysql> select ename from emp where ename like 'A%';
+-------+
| ename |
+-------+
| ALLEN |
| ADAMS |
+-------+
2 rows in set (0.00 sec)

// 方法二:用substr()函数
mysql> select ename from emp where substr(ename, 1, 1)='A';
+-------+
| ename |
+-------+
| ALLEN |
| ADAMS |
+-------+
2 rows in set (0.00 sec)

length(字段名):取长度

select length(ename) from emp;
mysql> select length(ename) from emp;
+---------------+
| length(ename) |
+---------------+
|             5 |
|             5 |
|             4 |
|             5 |
|             6 |
|             5 |
|             5 |
|             5 |
|             4 |
|             6 |
|             5 |
|             5 |
|             4 |
|             6 |
+---------------+
14 rows in set (0.00 sec)

concat(字符串, ...):字符串拼接

select concat(empno, ename, sal) from emp;
mysql> select concat(empno, ename, sal) from emp;
+---------------------------+
| concat(empno, ename, sal) |
+---------------------------+
| 7369SMITH800.00           |
| 7499ALLEN1600.00          |
| 7521WARD1250.00           |
| 7566JONES2975.00          |
| 7654MARTIN1250.00         |
| 7698BLAKE2850.00          |
| 7782CLARK2450.00          |
| 7788SCOTT3000.00          |
| 7839KING5000.00           |
| 7844TURNER1500.00         |
| 7876ADAMS1100.00          |
| 7900JAMES950.00           |
| 7902FORD3000.00           |
| 7934MILLER1300.00         |
+---------------------------+
14 rows in set (0.01 sec)

首字母大写

select concat(upper(substr(ename, 1, 1)), lower(substr(ename, 2, length(ename) - 1))) from emp;
mysql> select concat(upper(substr(ename, 1, 1)), lower(substr(ename, 2, length(ename) - 1))) from emp;
+--------------------------------------------------------------------------------+
| concat(upper(substr(ename, 1, 1)), lower(substr(ename, 2, length(ename) - 1))) |
+--------------------------------------------------------------------------------+
| Smith                                                                          |
| Allen                                                                          |
| Ward                                                                           |
| Jones                                                                          |
| Martin                                                                         |
| Blake                                                                          |
| Clark                                                                          |
| Scott                                                                          |
| King                                                                           |
| Turner                                                                         |
| Adams                                                                          |
| James                                                                          |
| Ford                                                                           |
| Miller                                                                         |
+--------------------------------------------------------------------------------+
14 rows in set (0.00 sec)

trim(字符串):去除前后空格

select * from emp where ename=trim('   king  ');
mysql> select * from emp where ename=trim('   king  ');
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
+-------+-------+-----------+------+------------+---------+------+--------+
1 row in set (0.00 sec)

round(数字):四舍五入

select 1234.567 as bieming from dept;
select round(1234.567, 0) as bieming from dept;
select round(1234.567, 1) as bieming from dept;
select round(1234.567, -1) as bieming from dept;
mysql> select 1234.567 as bieming from dept;
+----------+
| bieming  |
+----------+
| 1234.567 |
| 1234.567 |
| 1234.567 |
| 1234.567 |
+----------+
4 rows in set (0.00 sec)

mysql> select round(1234.567, 0) as bieming from dept;
+---------+
| bieming |
+---------+
|    1235 |
|    1235 |
|    1235 |
|    1235 |
+---------+
4 rows in set (0.01 sec)

mysql> select round(1234.567, 1) as bieming from dept;
+---------+
| bieming |
+---------+
|  1234.6 |
|  1234.6 |
|  1234.6 |
|  1234.6 |
+---------+
4 rows in set (0.00 sec)

mysql> select round(1234.567, -1) as bieming from dept;
+---------+
| bieming |
+---------+
|    1230 |
|    1230 |
|    1230 |
|    1230 |
+---------+
4 rows in set (0.01 sec)

rand():生成随机数

select rand() from emp;
select round(rand()*100, 0) from emp;
mysql> select rand() from emp;
+---------------------+
| rand()              |
+---------------------+
|  0.5602156506480794 |
|  0.1136106728702883 |
|   0.887406443140848 |
|  0.0962002278270202 |
|   0.818781840446202 |
|  0.8053085494835941 |
|  0.5701972568130095 |
| 0.43506066634791035 |
|  0.4647115920341682 |
| 0.01837599186075478 |
|  0.6977452139349144 |
| 0.43359812482595267 |
| 0.07475501305866522 |
| 0.07298072154911302 |
+---------------------+
14 rows in set (0.00 sec)

mysql> select round(rand()*100, 0) from emp;
+----------------------+
| round(rand()*100, 0) |
+----------------------+
|                    5 |
|                   31 |
|                   38 |
|                  100 |
|                   84 |
|                   22 |
|                   55 |
|                   12 |
|                   95 |
|                   40 |
|                   12 |
|                   41 |
|                   70 |
|                   26 |
+----------------------+
14 rows in set (0.00 sec)

ifnull(字段名, 为null时转换为什么值):数据为空时的处理

数据库中,只要有null参与的数学运算结果都为null,因此需要对null进行处理

ifnull(字段名, 如果数据的该字段为null就转为什么值)

select ename, sal+comm from emp;
select ename, sal+ifnull(comm, 0) from emp;
mysql> select ename, sal+comm from emp;
+--------+----------+
| ename  | sal+comm |
+--------+----------+
| SMITH  |     NULL |
| ALLEN  |  1900.00 |
| WARD   |  1750.00 |
| JONES  |     NULL |
| MARTIN |  2650.00 |
| BLAKE  |     NULL |
| CLARK  |     NULL |
| SCOTT  |     NULL |
| KING   |     NULL |
| TURNER |  1500.00 |
| ADAMS  |     NULL |
| JAMES  |     NULL |
| FORD   |     NULL |
| MILLER |     NULL |
+--------+----------+
14 rows in set (0.00 sec)

mysql> select ename, sal+ifnull(comm, 0) from emp;
+--------+---------------------+
| ename  | sal+ifnull(comm, 0) |
+--------+---------------------+
| SMITH  |              800.00 |
| ALLEN  |             1900.00 |
| WARD   |             1750.00 |
| JONES  |             2975.00 |
| MARTIN |             2650.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 |
+--------+---------------------+
14 rows in set (0.00 sec)

case when then when then else end:条件字段

当员工的工作岗位是MANAGER的时候,工资上调10%,当工作岗位是SALESMAN的时候,工资上调50%

select
	ename,
	job,
	sal as oldsal,
	(case job
		when job='manager' then sal*1.1
		when job='salesman' then sal*1.5
		else sal
	end)
	as newsal
from
	emp;
mysql> select
    ->	 	ename,
    -> 		job,
    -> 		sal as oldsal,
    -> 		(case job
    -> 			when job='manager' then sal*1.1
    -> 			when job='salesman' then sal*1.5
    -> 			else sal
    -> 		end)
    -> 		as newsal
    -> from
    -> 		emp;
+--------+-----------+---------+---------+
| ename  | job       | oldsal  | newsal  |
+--------+-----------+---------+---------+
| SMITH  | CLERK     |  800.00 |  880.00 |
| ALLEN  | SALESMAN  | 1600.00 | 1760.00 |
| WARD   | SALESMAN  | 1250.00 | 1375.00 |
| JONES  | MANAGER   | 2975.00 | 4462.50 |
| MARTIN | SALESMAN  | 1250.00 | 1375.00 |
| BLAKE  | MANAGER   | 2850.00 | 4275.00 |
| CLARK  | MANAGER   | 2450.00 | 3675.00 |
| SCOTT  | ANALYST   | 3000.00 | 3300.00 |
| KING   | PRESIDENT | 5000.00 | 5500.00 |
| TURNER | SALESMAN  | 1500.00 | 1650.00 |
| ADAMS  | CLERK     | 1100.00 | 1210.00 |
| JAMES  | CLERK     |  950.00 | 1045.00 |
| FORD   | ANALYST   | 3000.00 | 3300.00 |
| MILLER | CLERK     | 1300.00 | 1430.00 |
+--------+-----------+---------+---------+
14 rows in set, 14 warnings (0.00 sec)

多行处理函数

多行处理函数:输入多行,输出一行

多行处理函数又称分组函数、聚合函数

多行处理函数必须先分组,如果没有分组,则整张表默认为一组

count(字段名):计数

计算员工数量

select count(empno) from emp;
mysql> select count(empno) from emp;
+--------------+
| count(empno) |
+--------------+
|           14 |
+--------------+
1 row in set (0.00 sec)

sum(字段名):求和

计算工资和

select sum(sal) from emp;
mysql> select sum(sal) from emp;
+----------+
| sum(sal) |
+----------+
| 29025.00 |
+----------+
1 row in set (0.00 sec)

avg(字段名) :平均值

计算平均工资

select avg(sal) from emp;
mysql> select avg(sal) from emp;
+-------------+
| avg(sal)    |
+-------------+
| 2073.214286 |
+-------------+
1 row in set (0.00 sec)

max(字段名):最大值

查询最高工资

select max(sal) from emp;
mysql> select max(sal) from emp;
+----------+
| max(sal) |
+----------+
|  5000.00 |
+----------+
1 row in set (0.01 sec)

min(字段名):最小值

查询最低工资

select min(sal) from emp;
mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+
|   800.00 |
+----------+
1 row in set (0.00 sec)

分组函数自动忽略null

select sum(comm) from emp;
mysql> select sum(comm) from emp;
+-----------+
| sum(comm) |
+-----------+
|   2200.00 |
+-----------+
1 row in set (0.00 sec)

mysql> select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
|           4 |
+-------------+
1 row in set (0.00 sec)

注意count(*)和count(字段名)的区别

  • *代表一整行记录,而不可能有一整行记录都是null的(否则这条记录就没有意义)
  • count(*)输出总行数,count(字段名)统计该字段下所有不为NULL的元素的总数
select count(*) from emp;
select count(comm) from emp;
mysql> select count(*) from emp;
+----------+
| count(*) |
+----------+
|       14 |
+----------+
1 row in set (0.00 sec)

mysql> select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
|           4 |
+-------------+
1 row in set (0.00 sec)

分组函数不能用在where子句中

分组函数必须先分组才能使用,而where子句先于group by子句执行,因此where执行的时候还没有分组

找出工资高于最低工资的员工信息

select empno, ename, sal from emp where sal>min(sal);
mysql> select empno, ename, sal from emp where sal>min(sal);
ERROR 1111 (HY000): Invalid use of group function

所有分组函数可以组合起来一起用

select sum(sal), min(sal), max(sal), avg(sal), count(*) from emp;
mysql> select sum(sal), min(sal), max(sal), avg(sal), count(*) from emp;
+----------+----------+----------+-------------+----------+
| sum(sal) | min(sal) | max(sal) | avg(sal)    | count(*) |
+----------+----------+----------+-------------+----------+
| 29025.00 |   800.00 |  5000.00 | 2073.214286 |       14 |
+----------+----------+----------+-------------+----------+
1 row in set (0.00 sec)

分组查询

单个字段分组查询

select ... from ... group by <字段名>
select ... from ... where ... group by... order by ...
// 关键字顺序不能换
// 语句执行顺序为from -> where -> group by -> select -> order by
  • 查询每个岗位的工资和

    select job, sum(sal) from emp group by job;
    
    mysql> select job, sum(sal) from emp group by job;
    +-----------+----------+
    | job       | sum(sal) |
    +-----------+----------+
    | CLERK     |  4150.00 |
    | SALESMAN  |  5600.00 |
    | MANAGER   |  8275.00 |
    | ANALYST   |  6000.00 |
    | PRESIDENT |  5000.00 |
    +-----------+----------+
    5 rows in set (0.01 sec)
    
    mysql> select ename, job, sum(sal) from emp group by job;
    ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'bjpowernode.emp.ENAME' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
    // 加了group by之后,select子句后只能跟分组字段和分组函数,不能跟其他字段
    
  • 查询每个部门的最高薪资

    select deptno, max(sal) from emp group by deptno;
    
    mysql> select deptno, max(sal) from emp group by deptno;
    +--------+----------+
    | deptno | max(sal) |
    +--------+----------+
    |     20 |  3000.00 |
    |     30 |  2850.00 |
    |     10 |  5000.00 |
    +--------+----------+
    3 rows in set (0.01 sec)
    

多个字段分组查询

select ... from ... group by <字段名1>, <字段名2>, ... , <字段名n>
  • 查询每个部门,不同工作岗位的最高薪资

    select deptno, job, max(sal) from emp group by deptno, job;
    
    mysql> select deptno, job, max(sal) from emp group by deptno, job;
    +--------+-----------+----------+
    | deptno | job       | max(sal) |
    +--------+-----------+----------+
    |     20 | CLERK     |  1100.00 |
    |     30 | SALESMAN  |  1600.00 |
    |     20 | MANAGER   |  2975.00 |
    |     30 | MANAGER   |  2850.00 |
    |     10 | MANAGER   |  2450.00 |
    |     20 | ANALYST   |  3000.00 |
    |     10 | PRESIDENT |  5000.00 |
    |     30 | CLERK     |   950.00 |
    |     10 | CLERK     |  1300.00 |
    +--------+-----------+----------+
    9 rows in set (0.00 sec)
    

having子句

having子句用于过滤分组后的数据,不能单独使用,必须与group by搭配使用

select ... from ... group by ... having ...
  • 查询每个部门的最高薪资,要求显示最高薪资大于3000的

    select deptno, max(sal) from emp where sal>3000 group by deptno;
    select deptno, max(sal) from emp group by deptno having max(sal)>3000;
    
    mysql> select deptno, max(sal) from emp where sal>3000 group by deptno;
    +--------+----------+
    | deptno | max(sal) |
    +--------+----------+
    |     10 |  5000.00 |
    +--------+----------+
    1 row in set (0.00 sec)
    
    mysql> select deptno, max(sal) from emp group by deptno having max(sal)>3000;
    +--------+----------+
    | deptno | max(sal) |
    +--------+----------+
    |     10 |  5000.00 |
    +--------+----------+
    1 row in set (0.00 sec)
    
    // 前者先筛选出薪资大于3000的再分组,后者先分组再筛选出大于3000的,前者效率更高
    // 因此先考虑用where,where实现不了的采用having
    
  • 查询每个部门的平均薪资,要求显示平均薪资大于2500的

    select deptno, avg(sal) from emp group by deptno having avg(sal)>2500;
    
    mysql> select deptno, avg(sal) from emp group by deptno having avg(sal)>2500;
    +--------+-------------+
    | deptno | avg(sal)    |
    +--------+-------------+
    |     10 | 2916.666667 |
    +--------+-------------+
    1 row in set (0.00 sec)
    

总结

select ... from ... where ... group by ... having ... order by ...;

// 以上关键字只能按照这个顺序来,不能颠倒
// from -> where -> group by -> having -> select -> order by
/**
 * 先选择一张要查询的表(from),然后用where筛选数据,再group by分组,再用having筛选分组后的数据
 * 将这些数据select出来,进行order by排序,最后输出
 */
  • 查询除了manager之外,各部门平均薪资高于1500的岗位,并按平均薪资降序排列

    select
    	deptno, job, avg(sal) as avgsal
    from
    	emp
    where
    	job != 'manager'
    group by
    	deptno, job
    having
    	avg(sal)>1500
    order by
    	avgsal desc;
    
    mysql> select deptno, job, avg(sal) as avgsal from emp where job != 'manager' group by deptno, job having avg(sal)>1500 order by avgsal desc;
    +--------+-----------+-------------+
    | deptno | job       | avgsal      |
    +--------+-----------+-------------+
    |     10 | PRESIDENT | 5000.000000 |
    |     20 | ANALYST   | 3000.000000 |
    +--------+-----------+-------------+
    2 rows in set (0.00 sec)
    

补充distinct关键字

去除重复记录

只是将查询结果去除重复记录,因为是select关键字所以不会修改原表上的记录

select distinct <字段名> from ...
select distinct <字段名1>, <字段名2>, ... , <字段名n> from ...
select job from emp;		// 有重复数据
select distinct job from emp;	// distinct关键字去重
select count(distinct job) from emp;		// 可以嵌套在函数里面
mysql> select job from emp;		// 有重复数据
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| SALESMAN  |
| MANAGER   |
| SALESMAN  |
| MANAGER   |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
| SALESMAN  |
| CLERK     |
| CLERK     |
| ANALYST   |
| CLERK     |
+-----------+
14 rows in set (0.01 sec)

mysql> select distinct job from emp;	// distinct关键字去重
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+
5 rows in set (0.00 sec)

mysql> select count(distinct job) from emp;		// 可以嵌套在函数里面
+---------------------+
| count(distinct job) |
+---------------------+
|                   5 |
+---------------------+
1 row in set (0.00 sec)
select ename, distinct job from emp;	// 前面加其他字段会报错,distinct只能出现在所有字段的最前方
select distinct job, deptno from emp;	// distinct出现在最前方,表示job和deptno联合起来去重
mysql> select ename, distinct job from emp;	// 前面加其他字段会报错,distinct只能出现在所有字段的最前方
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'distinct job from emp' at line 1

mysql> select job, deptno from emp;
+-----------+--------+
| job       | deptno |
+-----------+--------+
| CLERK     |     20 |
| SALESMAN  |     30 |
| SALESMAN  |     30 |
| MANAGER   |     20 |
| SALESMAN  |     30 |
| MANAGER   |     30 |
| MANAGER   |     10 |
| ANALYST   |     20 |
| PRESIDENT |     10 |
| SALESMAN  |     30 |
| CLERK     |     20 |
| CLERK     |     30 |
| ANALYST   |     20 |
| CLERK     |     10 |
+-----------+--------+
14 rows in set (0.00 sec)

mysql> select distinct job, deptno from emp;	// distinct出现在最前方,表示job和deptno联合起来去重
+-----------+--------+
| job       | deptno |
+-----------+--------+
| CLERK     |     20 |
| SALESMAN  |     30 |
| MANAGER   |     20 |
| MANAGER   |     30 |
| MANAGER   |     10 |
| ANALYST   |     20 |
| PRESIDENT |     10 |
| CLERK     |     30 |
| CLERK     |     10 |
+-----------+--------+
9 rows in set (0.00 sec)

连接查询

连接查询的基本概念

从一张表中单独查询,称为单表查询。
emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中取部门名字
这种跨表查询,多张表联合起来查询数据,被称为连接查询

连接查询的分类

  • 根据语法年代分类:SQL92,SQL99(我们这里学习的是SQL99)
  • 根据表连接方式分类
    • 内连接:等值连接、非等值连接、自连接
    • 外连接:左外连接(左连接)、右外连接(右连接)
    • 全连接(不讲)

笛卡尔积现象

当两张表进行连接查询时,没有任何限制,会发生什么现象?
当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象

查询每个员工所在的部门名称

select ename, deptno from emp;
select deptno, dname from dept;
select ename, dname from emp, dept;
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 |
+--------+--------+
14 rows in set (0.00 sec)

mysql> select deptno, dname from dept;
+--------+------------+
| deptno | dname      |
+--------+------------+
|     10 | ACCOUNTING |
|     20 | RESEARCH   |
|     30 | SALES      |
|     40 | OPERATIONS |
+--------+------------+
4 rows in set (0.01 sec)

mysql> select ename, dname from emp, dept;
+--------+------------+
| ename  | dname      |
+--------+------------+
| SMITH  | OPERATIONS |
| SMITH  | SALES      |
| SMITH  | RESEARCH   |
| SMITH  | ACCOUNTING |
| ALLEN  | OPERATIONS |
| ALLEN  | SALES      |
| ALLEN  | RESEARCH   |
| ALLEN  | ACCOUNTING |
| WARD   | OPERATIONS |
| WARD   | SALES      |
| WARD   | RESEARCH   |
| WARD   | ACCOUNTING |
| JONES  | OPERATIONS |
| JONES  | SALES      |
| JONES  | RESEARCH   |
| JONES  | ACCOUNTING |
| MARTIN | OPERATIONS |
| MARTIN | SALES      |
| MARTIN | RESEARCH   |
| MARTIN | ACCOUNTING |
| BLAKE  | OPERATIONS |
| BLAKE  | SALES      |
| BLAKE  | RESEARCH   |
| BLAKE  | ACCOUNTING |
| CLARK  | OPERATIONS |
| CLARK  | SALES      |
| CLARK  | RESEARCH   |
| CLARK  | ACCOUNTING |
| SCOTT  | OPERATIONS |
| SCOTT  | SALES      |
| SCOTT  | RESEARCH   |
| SCOTT  | ACCOUNTING |
| KING   | OPERATIONS |
| KING   | SALES      |
| KING   | RESEARCH   |
| KING   | ACCOUNTING |
| TURNER | OPERATIONS |
| TURNER | SALES      |
| TURNER | RESEARCH   |
| TURNER | ACCOUNTING |
| ADAMS  | OPERATIONS |
| ADAMS  | SALES      |
| ADAMS  | RESEARCH   |
| ADAMS  | ACCOUNTING |
| JAMES  | OPERATIONS |
| JAMES  | SALES      |
| JAMES  | RESEARCH   |
| JAMES  | ACCOUNTING |
| FORD   | OPERATIONS |
| FORD   | SALES      |
| FORD   | RESEARCH   |
| FORD   | ACCOUNTING |
| MILLER | OPERATIONS |
| MILLER | SALES      |
| MILLER | RESEARCH   |
| MILLER | ACCOUNTING |
+--------+------------+
56 rows in set (0.00 sec)

怎么避免笛卡尔积现象?
连接时加条件,只有满足条件的记录才连接起来

select ename, dname from emp, dept where emp.deptno = dept.deptno;
select emp.ename, dept.dname from emp, dept where emp.deptno = dept.deptno;
select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno;	// SQL92的语法
mysql> select ename, dname from emp, dept where emp.deptno = dept.deptno;

mysql> select emp.ename, dept.dname from emp, dept where emp.deptno = dept.deptno;

mysql> select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno;	// SQL92的语法

+--------+------------+
| 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)

虽然避免了笛卡尔现象,但匹配次数还是56次,只是进行了四选一

内连接之等值连接

查询每个员工所在的部门名称

// SQL92语法
select
	e.ename, d.dname
from
	emp e, dept d
where
	e.deptno = d.deptno;
// 92语法的缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放到了where后面

// SQL99语法
select
	e.ename, d.dname
from
	emp e
(inner) join	// inner可以省略,带着inner可读性更好
	dept d
on
	e.deptno = d.deptno;	// 条件是等量关系,因此称为等值连接
// 99语法的优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where后面
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 |
+--------+------------+
14 rows in set (0.00 sec)

内连接之非等值连接

查询每个员工的薪资等级

select
	e.ename, e.sal , s.grade
from
	emp e
(inner) join
	salgrade s
on
	e.sal between s.losal and s.hisal	// 条件不是一个等量关系,称为非等值连接
order by
	s.grade asc, e.sal, e.ename;	// 甚至还能排个序
mysql> select
    -> e.ename, e.sal , s.grade
    -> from
    -> emp e
    -> join
    -> salgrade s
    -> on
    -> e.sal between s.losal and s.hisal
    -> order by
    -> s.grade asc, e.sal, e.ename;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| JAMES  |  950.00 |     1 |
| ADAMS  | 1100.00 |     1 |
| MARTIN | 1250.00 |     2 |
| WARD   | 1250.00 |     2 |
| MILLER | 1300.00 |     2 |
| TURNER | 1500.00 |     3 |
| ALLEN  | 1600.00 |     3 |
| CLARK  | 2450.00 |     4 |
| BLAKE  | 2850.00 |     4 |
| JONES  | 2975.00 |     4 |
| FORD   | 3000.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
+--------+---------+-------+
14 rows in set (0.00 sec)

内连接之自连接

查询员工的上级领导

select
	a.ename '员工', b.ename '领导'
from 
	emp a
join			// 一张表看成两张表,自连接
	emp b
on
	a.mgr = b.empno;		// 员工的领导编号 = 领导的员工编号
mysql> select
    -> a.ename '员工', b.ename '领导'
    -> from
    -> emp a
    -> join
    -> emp b
    -> on
    -> a.mgr = b.empno;
+--------+--------+
| 员工   | 领导   |
+--------+--------+
| SMITH  | FORD   |
| ALLEN  | BLAKE  |
| WARD   | BLAKE  |
| JONES  | KING   |
| MARTIN | BLAKE  |
| BLAKE  | KING   |
| CLARK  | KING   |
| SCOTT  | JONES  |
| TURNER | BLAKE  |
| ADAMS  | SCOTT  |
| JAMES  | BLAKE  |
| FORD   | JONES  |
| MILLER | CLARK  |
+--------+--------+
13 rows in set (0.00 sec)

外连接

select
	e.ename, d.dname
from
	emp e
(inner) join
	dept d
on
	e.deptno = d.deptno;	// 内连接的特点:两张表没有主次关系,只把完全能够匹配上这个条件的数据查询出来
	
select
	e.ename, d.dname
from
	emp e
right (outer) join		// outer可以省略,带着可读性强
	dept d
on
	e.deptno = d.deptno;
/**
 * 外连接的特点:两张表有主次关系,主次关系通过left和right关键字来表示
 * right代表将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表
 * 外连接的查询结果条数 >= 内连接的查询结果条数
 */
mysql> select e.ename, d.dname from emp e right join dept d on e.deptno = d.deptno;
+--------+------------+
| ename  | dname      |
+--------+------------+
| MILLER | ACCOUNTING |
| KING   | ACCOUNTING |
| CLARK  | ACCOUNTING |
| FORD   | RESEARCH   |
| ADAMS  | RESEARCH   |
| SCOTT  | RESEARCH   |
| JONES  | RESEARCH   |
| SMITH  | RESEARCH   |
| JAMES  | SALES      |
| TURNER | SALES      |
| BLAKE  | SALES      |
| MARTIN | SALES      |
| WARD   | SALES      |
| ALLEN  | SALES      |
| NULL   | OPERATIONS |		// 右表是主表,所有数据都会显示出来,匹配不上就显示null
+--------+------------+
15 rows in set (0.00 sec)

查询员工的上级领导,显示所有员工名字和领导名

select
	a.ename '员工', b.ename '领导'
from 
	emp a
left join
	emp b
on
	a.mgr = b.empno;		// 员工的领导编号 = 领导的员工编号
mysql> select
    -> a.ename '员工', b.ename '领导'
    -> from
    -> emp a
    -> left join
    -> emp b
    -> on
    -> a.mgr = b.empno;
+--------+--------+
| 员工   | 领导   |
+--------+--------+
| SMITH  | FORD   |
| ALLEN  | BLAKE  |
| WARD   | BLAKE  |
| JONES  | KING   |
| MARTIN | BLAKE  |
| BLAKE  | KING   |
| CLARK  | KING   |
| SCOTT  | JONES  |
| KING   | NULL   |
| TURNER | BLAKE  |
| ADAMS  | SCOTT  |
| JAMES  | BLAKE  |
| FORD   | JONES  |
| MILLER | CLARK  |
+--------+--------+
14 rows in set (0.00 sec)

全连接

全连接相当于外连接的时候两张表都是主表,MySql不支持全连接,在此不再讨论

多表连接

内外连接可以混合

select
	...
from
	a
join b on <a和b的连接条件>
join c on <a和c的连接条件>
join d on <a和d的连接条件>

找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级

select
	e.ename, d.dname, e.sal, 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;
mysql> select
    -> e.ename, d.dname, e.sal, 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      | sal     | grade |
+--------+------------+---------+-------+
| SMITH  | RESEARCH   |  800.00 |     1 |
| ALLEN  | SALES      | 1600.00 |     3 |
| WARD   | SALES      | 1250.00 |     2 |
| JONES  | RESEARCH   | 2975.00 |     4 |
| MARTIN | SALES      | 1250.00 |     2 |
| BLAKE  | SALES      | 2850.00 |     4 |
| CLARK  | ACCOUNTING | 2450.00 |     4 |
| SCOTT  | RESEARCH   | 3000.00 |     4 |
| KING   | ACCOUNTING | 5000.00 |     5 |
| TURNER | SALES      | 1500.00 |     3 |
| ADAMS  | RESEARCH   | 1100.00 |     1 |
| JAMES  | SALES      |  950.00 |     1 |
| FORD   | RESEARCH   | 3000.00 |     4 |
| MILLER | ACCOUNTING | 1300.00 |     2 |
+--------+------------+---------+-------+
14 rows in set (0.00 sec)

找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名、领导名、部门名、薪资、薪资等级

select
	e.ename, l.ename, d.dname, e.sal, 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
left join
	emp l
on
	e.mgr = l.empno;
mysql> select
    -> e.ename, l.ename, d.dname, e.sal, 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
    -> left join
    -> emp l
    -> on
    -> e.mgr = l.empno;
+--------+-------+------------+---------+-------+
| ename  | ename | dname      | sal     | grade |
+--------+-------+------------+---------+-------+
| SMITH  | FORD  | RESEARCH   |  800.00 |     1 |
| ALLEN  | BLAKE | SALES      | 1600.00 |     3 |
| WARD   | BLAKE | SALES      | 1250.00 |     2 |
| JONES  | KING  | RESEARCH   | 2975.00 |     4 |
| MARTIN | BLAKE | SALES      | 1250.00 |     2 |
| BLAKE  | KING  | SALES      | 2850.00 |     4 |
| CLARK  | KING  | ACCOUNTING | 2450.00 |     4 |
| SCOTT  | JONES | RESEARCH   | 3000.00 |     4 |
| KING   | NULL  | ACCOUNTING | 5000.00 |     5 |
| TURNER | BLAKE | SALES      | 1500.00 |     3 |
| ADAMS  | SCOTT | RESEARCH   | 1100.00 |     1 |
| JAMES  | BLAKE | SALES      |  950.00 |     1 |
| FORD   | JONES | RESEARCH   | 3000.00 |     4 |
| MILLER | CLARK | ACCOUNTING | 1300.00 |     2 |
+--------+-------+------------+---------+-------+
14 rows in set (0.00 sec)

子查询

子查询的基本概念

子查询:select语句中嵌套select语句,被嵌套的select语句称为子查询。

select
	<select子查询>
from
	<select子查询>
where
	<select子查询>

where中的子查询

找出工资高于最低工资的员工信息

select ename, sal from emp where sal>min(sal);
select min(sal) from emp;
select ename, sal from emp where sal>800;
select ename, sal from emp where sal>(select min(sal) from emp);
mysql> select ename, sal from emp where sal>min(sal);
ERROR 1111 (HY000): Invalid use of group function	// where子句中不能使用分组函数

// 思路
// 先找出最低工资
mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+
|   800.00 |
+----------+
1 row in set (0.01 sec)

// 再找出比最低工资高的
mysql> select ename, sal from emp where sal>800;
+--------+---------+
| ename  | sal     |
+--------+---------+
| 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 |
+--------+---------+
13 rows in set (0.00 sec)

// 合并
mysql> select ename, sal from emp where sal>(select min(sal) from emp);
+--------+---------+
| ename  | sal     |
+--------+---------+
| 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 |
+--------+---------+
13 rows in set (0.01 sec)

from中的子查询

from中的子查询,可以将子查询的结果当成一张临时表

找出每个岗位的平均工资的薪资等级

select job, avg(sal) from emp group by job;
select
	a.job, a.avgsal, s.grade
from
	(select job, avg(sal) avgsal from emp group by job) a	// 注意去掉分号,带有分组函数的要起别名
join
	salgrade s
on
	a.avgsal between losal and hisal;
// 先找出每个岗位的平均工资
mysql> select job, avg(sal) from emp group by job;
+-----------+-------------+
| job       | avg(sal)    |
+-----------+-------------+
| CLERK     | 1037.500000 |
| SALESMAN  | 1400.000000 |
| MANAGER   | 2758.333333 |
| ANALYST   | 3000.000000 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
5 rows in set (0.00 sec)


// 再将这张临时表与薪资等级表连接,找出薪资等级
mysql> select
    -> a.job, a.avgsal, s.grade
    -> from
    -> (select job, avg(sal) avgsal from emp group by job) a
    -> join
    -> salgrade s
    -> on
    -> a.avgsal between losal and hisal;
+-----------+-------------+-------+
| job       | avgsal      | grade |
+-----------+-------------+-------+
| CLERK     | 1037.500000 |     1 |
| SALESMAN  | 1400.000000 |     2 |
| MANAGER   | 2758.333333 |     4 |
| ANALYST   | 3000.000000 |     4 |
| PRESIDENT | 5000.000000 |     5 |
+-----------+-------------+-------+
5 rows in set (0.00 sec)

select中的子查询

了解即可,可读性比较差

查询每个员工所在的部门名

select e.ename, e.deptno, (select d.dname from dept d where e.deptno = d.deptno) dname from emp e;	
// 只要子查询的查询结果多于1条记录,该查询就报错
mysql> select e.ename, e.deptno, (select d.dname from dept d where e.deptno = d.deptno) dname from emp e;		// 只要子查询的查询结果多于1条记录,该查询就报错
+--------+--------+------------+
| ename  | deptno | dname      |
+--------+--------+------------+
| SMITH  |     20 | RESEARCH   |
| ALLEN  |     30 | SALES      |
| WARD   |     30 | SALES      |
| JONES  |     20 | RESEARCH   |
| MARTIN |     30 | SALES      |
| BLAKE  |     30 | SALES      |
| CLARK  |     10 | ACCOUNTING |
| SCOTT  |     20 | RESEARCH   |
| KING   |     10 | ACCOUNTING |
| TURNER |     30 | SALES      |
| ADAMS  |     20 | RESEARCH   |
| JAMES  |     30 | SALES      |
| FORD   |     20 | RESEARCH   |
| MILLER |     10 | ACCOUNTING |
+--------+--------+------------+
14 rows in set (0.00 sec)

union合并查询结果集

对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的增长
union在减少匹配次数的情况下,还可以完成两个结果集的拼接

a10条记录,b10条记录,c10条记录

  • 第一种方式:a连接b连接c:匹配次数是:1000次
  • 第二种方式:a连接b一个结果: 10 × 10 = 100 次 10 \times 10 = 100次 10×10=100;a 连接c一个结果: 10 × 10 = 100 次 10 \times 10 = 100次 10×10=100,使用union的话是: 100 + 100 = 200 次 100 + 100 = 200次 100+100=200

union进行结果合并时,要求列数相同,且列的数据类型也要相同

查询工作岗位是manager和salesman的员工

select ename, job from emp where job = 'manager' or job = 'salesman';
select ename, job from emp where job in('manager', 'salesman');
select ename, job from emp where job = 'manager'
union
select ename, job from emp where job = 'salesman';
mysql> select ename, job from emp where job = 'manager' or job = 'salesman';
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.00 sec)

mysql> select ename, job from emp where job in('manager', 'salesman');
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.00 sec)

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 |
+--------+----------+
7 rows in set (0.00 sec)

limit取部分查询结果集

limit取部分查询结果集,通常用在分页中

按照薪资降序,取出排名在前5名的员工

limit 起始下标, 长度
limit 长度	// 默认从0开始
// limit在order by执行之后再执行
select ename, sal from emp order by sal desc limit 5;
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 |
+-------+---------+
5 rows in set (0.00 sec)

mysql> select ename, sal from emp order by sal desc limit 0, 5;
+-------+---------+
| ename | sal     |
+-------+---------+
| KING  | 5000.00 |
| SCOTT | 3000.00 |
| FORD  | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.00 sec)

取出工资排名在[3-5]名的员工?

select ename, sal from emp order by sal desc limit 2, 3;
mysql> select ename, sal from emp order by sal desc limit 2, 3;
// 2表示起始位置从下标2开始,就是第三条记录,3表示长度
+-------+---------+
| ename | sal     |
+-------+---------+
| FORD  | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
3 rows in set (0.00 sec)

每页显示3条记录

第1页:limit 0, 3;第2页:limit 3, 3;第3页:limit 6, 3;第4页:limit 9, 3

每页显示pageSize条记录,第pageNo页:limit (pageNo-1)*pageSize, pageSize

DQL语句大总结

select ... from ... where ... group by ... having ... order by ... limit ...;

// 以上关键字只能按照这个顺序来,不能颠倒
// from -> where -> group by -> having -> select -> order by -> limit
/**
 * 先选择一张要查询的表(from),然后用where筛选数据,再group by分组,再用having筛选分组后的数据
 * 将这些数据select出来,进行order by排序,最后limit切片输出
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值